slirp: Rework external configuration interface
With the internal IP configuration made more flexible, we can now enhance the user interface. This patch adds a number of new options to "-net user": net (address and mask), host, dhcpstart, dns and smbserver. It also renames "redir" to "hostfwd" and "channel" to "guestfwd" in order to (hopefully) clarify their meanings. The format of guestfwd is extended so that the user can define not only the port but also the virtual server's IP address the forwarding starts from. Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
parent
a13a4126c8
commit
c92ef6a22d
316
net.c
316
net.c
@ -669,12 +669,14 @@ static void config_error(Monitor *mon, const char *fmt, ...)
|
|||||||
|
|
||||||
/* slirp network adapter */
|
/* slirp network adapter */
|
||||||
|
|
||||||
#define SLIRP_CFG_REDIR 1
|
#define SLIRP_CFG_HOSTFWD 1
|
||||||
|
#define SLIRP_CFG_LEGACY 2
|
||||||
|
|
||||||
struct slirp_config_str {
|
struct slirp_config_str {
|
||||||
struct slirp_config_str *next;
|
struct slirp_config_str *next;
|
||||||
int flags;
|
int flags;
|
||||||
char str[1024];
|
char str[1024];
|
||||||
|
int legacy_format;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int slirp_inited;
|
static int slirp_inited;
|
||||||
@ -683,13 +685,14 @@ const char *legacy_tftp_prefix;
|
|||||||
const char *legacy_bootp_filename;
|
const char *legacy_bootp_filename;
|
||||||
static VLANClientState *slirp_vc;
|
static VLANClientState *slirp_vc;
|
||||||
|
|
||||||
static void slirp_redirection(Monitor *mon, const char *redir_str);
|
static void slirp_hostfwd(Monitor *mon, const char *redir_str);
|
||||||
static void vmchannel_init(Monitor *mon, const char *config_str);
|
static void slirp_guestfwd(Monitor *mon, const char *config_str,
|
||||||
|
int legacy_format);
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
static const char *legacy_smb_export;
|
static const char *legacy_smb_export;
|
||||||
|
|
||||||
static void slirp_smb(const char *exported_dir);
|
static void slirp_smb(const char *exported_dir, struct in_addr vserver_addr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int slirp_can_output(void)
|
int slirp_can_output(void)
|
||||||
@ -731,31 +734,122 @@ static void net_slirp_cleanup(VLANClientState *vc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
|
static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
|
||||||
const char *name, int restricted, const char *ip,
|
const char *name, int restricted,
|
||||||
const char *tftp_export, const char *bootfile,
|
const char *vnetwork, const char *vhost,
|
||||||
const char *smb_export)
|
const char *vhostname, const char *tftp_export,
|
||||||
|
const char *bootfile, const char *vdhcp_start,
|
||||||
|
const char *vnameserver, const char *smb_export,
|
||||||
|
const char *vsmbserver)
|
||||||
{
|
{
|
||||||
if (slirp_in_use) {
|
if (slirp_in_use) {
|
||||||
/* slirp only supports a single instance so far */
|
/* slirp only supports a single instance so far */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (!slirp_inited) {
|
if (!slirp_inited) {
|
||||||
|
/* default settings according to historic slirp */
|
||||||
|
struct in_addr net = { .s_addr = htonl(0x0a000000) }; /* 10.0.0.0 */
|
||||||
|
struct in_addr mask = { .s_addr = htonl(0xff000000) }; /* 255.0.0.0 */
|
||||||
|
struct in_addr host = { .s_addr = htonl(0x0a000202) }; /* 10.0.2.2 */
|
||||||
|
struct in_addr dhcp = { .s_addr = htonl(0x0a00020f) }; /* 10.0.2.15 */
|
||||||
|
struct in_addr dns = { .s_addr = htonl(0x0a000203) }; /* 10.0.2.3 */
|
||||||
|
#ifndef _WIN32
|
||||||
|
struct in_addr smbsrv = { .s_addr = 0 };
|
||||||
|
#endif
|
||||||
|
char buf[20];
|
||||||
|
uint32_t addr;
|
||||||
|
int shift;
|
||||||
|
char *end;
|
||||||
|
|
||||||
if (!tftp_export) {
|
if (!tftp_export) {
|
||||||
tftp_export = legacy_tftp_prefix;
|
tftp_export = legacy_tftp_prefix;
|
||||||
}
|
}
|
||||||
if (!bootfile) {
|
if (!bootfile) {
|
||||||
bootfile = legacy_bootp_filename;
|
bootfile = legacy_bootp_filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vnetwork) {
|
||||||
|
if (get_str_sep(buf, sizeof(buf), &vnetwork, '/') < 0) {
|
||||||
|
if (!inet_aton(vnetwork, &net)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
addr = ntohl(net.s_addr);
|
||||||
|
if (!(addr & 0x80000000)) {
|
||||||
|
mask.s_addr = htonl(0xff000000); /* class A */
|
||||||
|
} else if ((addr & 0xfff00000) == 0xac100000) {
|
||||||
|
mask.s_addr = htonl(0xfff00000); /* priv. 172.16.0.0/12 */
|
||||||
|
} else if ((addr & 0xc0000000) == 0x80000000) {
|
||||||
|
mask.s_addr = htonl(0xffff0000); /* class B */
|
||||||
|
} else if ((addr & 0xffff0000) == 0xc0a80000) {
|
||||||
|
mask.s_addr = htonl(0xffff0000); /* priv. 192.168.0.0/16 */
|
||||||
|
} else if ((addr & 0xffff0000) == 0xc6120000) {
|
||||||
|
mask.s_addr = htonl(0xfffe0000); /* tests 198.18.0.0/15 */
|
||||||
|
} else if ((addr & 0xe0000000) == 0xe0000000) {
|
||||||
|
mask.s_addr = htonl(0xffffff00); /* class C */
|
||||||
|
} else {
|
||||||
|
mask.s_addr = htonl(0xfffffff0); /* multicast/reserved */
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!inet_aton(buf, &net)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
shift = strtol(vnetwork, &end, 10);
|
||||||
|
if (*end != '\0') {
|
||||||
|
if (!inet_aton(vnetwork, &mask)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else if (shift < 4 || shift > 32) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
mask.s_addr = htonl(0xffffffff << (32 - shift));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
net.s_addr &= mask.s_addr;
|
||||||
|
host.s_addr = net.s_addr | (htonl(0x0202) & ~mask.s_addr);
|
||||||
|
dhcp.s_addr = net.s_addr | (htonl(0x020f) & ~mask.s_addr);
|
||||||
|
dns.s_addr = net.s_addr | (htonl(0x0203) & ~mask.s_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vhost && !inet_aton(vhost, &host)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((host.s_addr & mask.s_addr) != net.s_addr) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vdhcp_start && !inet_aton(vdhcp_start, &dhcp)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((dhcp.s_addr & mask.s_addr) != net.s_addr ||
|
||||||
|
dhcp.s_addr == host.s_addr || dhcp.s_addr == dns.s_addr) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vnameserver && !inet_aton(vnameserver, &dns)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((dns.s_addr & mask.s_addr) != net.s_addr ||
|
||||||
|
dns.s_addr == host.s_addr) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
if (vsmbserver && !inet_aton(vsmbserver, &smbsrv)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
slirp_init(restricted, net, mask, host, vhostname, tftp_export,
|
||||||
|
bootfile, dhcp, dns);
|
||||||
slirp_inited = 1;
|
slirp_inited = 1;
|
||||||
slirp_init(restricted, ip, tftp_export, bootfile);
|
|
||||||
|
|
||||||
while (slirp_configs) {
|
while (slirp_configs) {
|
||||||
struct slirp_config_str *config = slirp_configs;
|
struct slirp_config_str *config = slirp_configs;
|
||||||
|
|
||||||
if (config->flags & SLIRP_CFG_REDIR) {
|
if (config->flags & SLIRP_CFG_HOSTFWD) {
|
||||||
slirp_redirection(mon, config->str);
|
slirp_hostfwd(mon, config->str);
|
||||||
} else {
|
} else {
|
||||||
vmchannel_init(mon, config->str);
|
slirp_guestfwd(mon, config->str,
|
||||||
|
config->flags & SLIRP_CFG_LEGACY);
|
||||||
}
|
}
|
||||||
slirp_configs = config->next;
|
slirp_configs = config->next;
|
||||||
qemu_free(config);
|
qemu_free(config);
|
||||||
@ -765,7 +859,7 @@ static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
|
|||||||
smb_export = legacy_smb_export;
|
smb_export = legacy_smb_export;
|
||||||
}
|
}
|
||||||
if (smb_export) {
|
if (smb_export) {
|
||||||
slirp_smb(smb_export);
|
slirp_smb(smb_export, smbsrv);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -777,7 +871,7 @@ static int net_slirp_init(Monitor *mon, VLANState *vlan, const char *model,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void net_slirp_redir_rm(Monitor *mon, const char *port_str)
|
static void net_slirp_hostfwd_remove(Monitor *mon, const char *port_str)
|
||||||
{
|
{
|
||||||
int host_port;
|
int host_port;
|
||||||
char buf[256] = "";
|
char buf[256] = "";
|
||||||
@ -803,23 +897,24 @@ static void net_slirp_redir_rm(Monitor *mon, const char *port_str)
|
|||||||
|
|
||||||
host_port = atoi(p);
|
host_port = atoi(p);
|
||||||
|
|
||||||
n = slirp_redir_rm(is_udp, host_port);
|
n = slirp_remove_hostfwd(is_udp, host_port);
|
||||||
|
|
||||||
monitor_printf(mon, "removed %d redirections to %s port %d\n", n,
|
monitor_printf(mon, "removed %d host forwarding rules for %s port %d\n",
|
||||||
is_udp ? "udp" : "tcp", host_port);
|
n, is_udp ? "udp" : "tcp", host_port);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fail_syntax:
|
fail_syntax:
|
||||||
monitor_printf(mon, "invalid format\n");
|
monitor_printf(mon, "invalid format\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void slirp_redirection(Monitor *mon, const char *redir_str)
|
static void slirp_hostfwd(Monitor *mon, const char *redir_str)
|
||||||
{
|
{
|
||||||
struct in_addr guest_addr;
|
struct in_addr guest_addr = { .s_addr = 0 };
|
||||||
int host_port, guest_port;
|
int host_port, guest_port;
|
||||||
const char *p;
|
const char *p;
|
||||||
char buf[256], *r;
|
char buf[256];
|
||||||
int is_udp;
|
int is_udp;
|
||||||
|
char *end;
|
||||||
|
|
||||||
p = redir_str;
|
p = redir_str;
|
||||||
if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
|
if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
|
||||||
@ -836,33 +931,31 @@ static void slirp_redirection(Monitor *mon, const char *redir_str)
|
|||||||
if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
|
if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
|
||||||
goto fail_syntax;
|
goto fail_syntax;
|
||||||
}
|
}
|
||||||
host_port = strtol(buf, &r, 0);
|
host_port = strtol(buf, &end, 0);
|
||||||
if (r == buf) {
|
if (*end != '\0' || host_port < 1 || host_port > 65535) {
|
||||||
goto fail_syntax;
|
goto fail_syntax;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
|
if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
|
||||||
goto fail_syntax;
|
goto fail_syntax;
|
||||||
}
|
}
|
||||||
if (buf[0] == '\0') {
|
if (buf[0] != '\0' && !inet_aton(buf, &guest_addr)) {
|
||||||
pstrcpy(buf, sizeof(buf), "10.0.2.15");
|
|
||||||
}
|
|
||||||
if (!inet_aton(buf, &guest_addr)) {
|
|
||||||
goto fail_syntax;
|
goto fail_syntax;
|
||||||
}
|
}
|
||||||
|
|
||||||
guest_port = strtol(p, &r, 0);
|
guest_port = strtol(p, &end, 0);
|
||||||
if (r == p) {
|
if (*end != '\0' || guest_port < 1 || guest_port > 65535) {
|
||||||
goto fail_syntax;
|
goto fail_syntax;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slirp_redir(is_udp, host_port, guest_addr, guest_port) < 0) {
|
if (slirp_add_hostfwd(is_udp, host_port, guest_addr, guest_port) < 0) {
|
||||||
config_error(mon, "could not set up redirection '%s'\n", redir_str);
|
config_error(mon, "could not set up host forwarding rule '%s'\n",
|
||||||
|
redir_str);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fail_syntax:
|
fail_syntax:
|
||||||
config_error(mon, "invalid redirection format '%s'\n", redir_str);
|
config_error(mon, "invalid host forwarding rule '%s'\n", redir_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
void net_slirp_redir(Monitor *mon, const char *redir_str, const char *redir_opt2)
|
void net_slirp_redir(Monitor *mon, const char *redir_str, const char *redir_opt2)
|
||||||
@ -875,7 +968,7 @@ void net_slirp_redir(Monitor *mon, const char *redir_str, const char *redir_opt2
|
|||||||
} else {
|
} else {
|
||||||
config = qemu_malloc(sizeof(*config));
|
config = qemu_malloc(sizeof(*config));
|
||||||
pstrcpy(config->str, sizeof(config->str), redir_str);
|
pstrcpy(config->str, sizeof(config->str), redir_str);
|
||||||
config->flags = SLIRP_CFG_REDIR;
|
config->flags = SLIRP_CFG_HOSTFWD;
|
||||||
config->next = slirp_configs;
|
config->next = slirp_configs;
|
||||||
slirp_configs = config;
|
slirp_configs = config;
|
||||||
}
|
}
|
||||||
@ -883,11 +976,11 @@ void net_slirp_redir(Monitor *mon, const char *redir_str, const char *redir_opt2
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(redir_str, "remove")) {
|
if (!strcmp(redir_str, "remove")) {
|
||||||
net_slirp_redir_rm(mon, redir_opt2);
|
net_slirp_hostfwd_remove(mon, redir_opt2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
slirp_redirection(mon, redir_str);
|
slirp_hostfwd(mon, redir_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
@ -925,7 +1018,7 @@ static void smb_exit(void)
|
|||||||
erase_dir(smb_dir);
|
erase_dir(smb_dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void slirp_smb(const char *exported_dir)
|
static void slirp_smb(const char *exported_dir, struct in_addr vserver_addr)
|
||||||
{
|
{
|
||||||
char smb_conf[1024];
|
char smb_conf[1024];
|
||||||
char smb_cmdline[1024];
|
char smb_cmdline[1024];
|
||||||
@ -971,19 +1064,24 @@ static void slirp_smb(const char *exported_dir)
|
|||||||
snprintf(smb_cmdline, sizeof(smb_cmdline), "%s -s %s",
|
snprintf(smb_cmdline, sizeof(smb_cmdline), "%s -s %s",
|
||||||
SMBD_COMMAND, smb_conf);
|
SMBD_COMMAND, smb_conf);
|
||||||
|
|
||||||
slirp_add_exec(0, smb_cmdline, 4, 139);
|
if (slirp_add_exec(0, smb_cmdline, vserver_addr, 139) < 0) {
|
||||||
|
fprintf(stderr, "conflicting/invalid smbserver address\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* automatic user mode samba server configuration (legacy interface) */
|
/* automatic user mode samba server configuration (legacy interface) */
|
||||||
void net_slirp_smb(const char *exported_dir)
|
void net_slirp_smb(const char *exported_dir)
|
||||||
{
|
{
|
||||||
|
struct in_addr vserver_addr = { .s_addr = 0 };
|
||||||
|
|
||||||
if (legacy_smb_export) {
|
if (legacy_smb_export) {
|
||||||
fprintf(stderr, "-smb given twice\n");
|
fprintf(stderr, "-smb given twice\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
legacy_smb_export = exported_dir;
|
legacy_smb_export = exported_dir;
|
||||||
if (slirp_inited) {
|
if (slirp_inited) {
|
||||||
slirp_smb(exported_dir);
|
slirp_smb(exported_dir, vserver_addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -994,51 +1092,85 @@ void do_info_slirp(Monitor *mon)
|
|||||||
slirp_stats();
|
slirp_stats();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VMChannel {
|
struct GuestFwd {
|
||||||
CharDriverState *hd;
|
CharDriverState *hd;
|
||||||
|
struct in_addr server;
|
||||||
int port;
|
int port;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int vmchannel_can_read(void *opaque)
|
static int guestfwd_can_read(void *opaque)
|
||||||
{
|
{
|
||||||
struct VMChannel *vmc = (struct VMChannel*)opaque;
|
struct GuestFwd *fwd = opaque;
|
||||||
return slirp_socket_can_recv(4, vmc->port);
|
return slirp_socket_can_recv(fwd->server, fwd->port);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vmchannel_read(void *opaque, const uint8_t *buf, int size)
|
static void guestfwd_read(void *opaque, const uint8_t *buf, int size)
|
||||||
{
|
{
|
||||||
struct VMChannel *vmc = (struct VMChannel*)opaque;
|
struct GuestFwd *fwd = opaque;
|
||||||
slirp_socket_recv(4, vmc->port, buf, size);
|
slirp_socket_recv(fwd->server, fwd->port, buf, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vmchannel_init(Monitor *mon, const char *config_str)
|
static void slirp_guestfwd(Monitor *mon, const char *config_str,
|
||||||
|
int legacy_format)
|
||||||
{
|
{
|
||||||
struct VMChannel *vmc;
|
struct in_addr server = { .s_addr = 0 };
|
||||||
char *devname;
|
struct GuestFwd *fwd;
|
||||||
char name[20];
|
const char *p;
|
||||||
|
char buf[128];
|
||||||
|
char *end;
|
||||||
int port;
|
int port;
|
||||||
|
|
||||||
port = strtol(config_str, &devname, 10);
|
p = config_str;
|
||||||
if (port < 1 || port > 65535 || *devname != ':') {
|
if (legacy_format) {
|
||||||
config_error(mon, "invalid vmchannel port number\n");
|
if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
|
||||||
|
goto fail_syntax;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
|
||||||
|
goto fail_syntax;
|
||||||
|
}
|
||||||
|
if (strcmp(buf, "tcp") && buf[0] != '\0') {
|
||||||
|
goto fail_syntax;
|
||||||
|
}
|
||||||
|
if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
|
||||||
|
goto fail_syntax;
|
||||||
|
}
|
||||||
|
if (buf[0] != '\0' && !inet_aton(buf, &server)) {
|
||||||
|
goto fail_syntax;
|
||||||
|
}
|
||||||
|
if (get_str_sep(buf, sizeof(buf), &p, '-') < 0) {
|
||||||
|
goto fail_syntax;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
port = strtol(buf, &end, 10);
|
||||||
|
if (*end != '\0' || port < 1 || port > 65535) {
|
||||||
|
goto fail_syntax;
|
||||||
|
}
|
||||||
|
|
||||||
|
fwd = qemu_malloc(sizeof(struct GuestFwd));
|
||||||
|
snprintf(buf, sizeof(buf), "guestfwd.tcp:%d", port);
|
||||||
|
fwd->hd = qemu_chr_open(buf, p, NULL);
|
||||||
|
if (!fwd->hd) {
|
||||||
|
config_error(mon, "could not open guest forwarding device '%s'\n",
|
||||||
|
buf);
|
||||||
|
qemu_free(fwd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
devname++;
|
fwd->server = server;
|
||||||
|
fwd->port = port;
|
||||||
|
|
||||||
vmc = qemu_malloc(sizeof(struct VMChannel));
|
if (slirp_add_exec(3, fwd->hd, server, port) < 0) {
|
||||||
snprintf(name, sizeof(name), "vmchannel%d", port);
|
config_error(mon, "conflicting/invalid host:port in guest forwarding "
|
||||||
vmc->hd = qemu_chr_open(name, devname, NULL);
|
"rule '%s'\n", config_str);
|
||||||
if (!vmc->hd) {
|
qemu_free(fwd);
|
||||||
config_error(mon, "could not open vmchannel device '%s'\n", devname);
|
|
||||||
qemu_free(vmc);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
vmc->port = port;
|
qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read,
|
||||||
|
NULL, fwd);
|
||||||
slirp_add_exec(3, vmc->hd, 4, port);
|
|
||||||
qemu_chr_add_handlers(vmc->hd, vmchannel_can_read, vmchannel_read,
|
|
||||||
NULL, vmc);
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
fail_syntax:
|
||||||
|
config_error(mon, "invalid guest forwarding rule '%s'\n", config_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_SLIRP */
|
#endif /* CONFIG_SLIRP */
|
||||||
@ -2252,15 +2384,21 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
|
|||||||
#ifdef CONFIG_SLIRP
|
#ifdef CONFIG_SLIRP
|
||||||
if (!strcmp(device, "user")) {
|
if (!strcmp(device, "user")) {
|
||||||
static const char * const slirp_params[] = {
|
static const char * const slirp_params[] = {
|
||||||
"vlan", "name", "hostname", "restrict", "ip", "tftp", "bootfile",
|
"vlan", "name", "hostname", "restrict", "ip", "net", "host",
|
||||||
"smb", "redir", "channel", NULL
|
"tftp", "bootfile", "dhcpstart", "dns", "smb", "smbserver",
|
||||||
|
"hostfwd", "guestfwd", NULL
|
||||||
};
|
};
|
||||||
struct slirp_config_str *config;
|
struct slirp_config_str *config;
|
||||||
|
int restricted = 0;
|
||||||
|
char *vnet = NULL;
|
||||||
|
char *vhost = NULL;
|
||||||
|
char *vhostname = NULL;
|
||||||
char *tftp_export = NULL;
|
char *tftp_export = NULL;
|
||||||
char *bootfile = NULL;
|
char *bootfile = NULL;
|
||||||
|
char *vdhcp_start = NULL;
|
||||||
|
char *vnamesrv = NULL;
|
||||||
char *smb_export = NULL;
|
char *smb_export = NULL;
|
||||||
int restricted = 0;
|
char *vsmbsrv = NULL;
|
||||||
char *ip = NULL;
|
|
||||||
const char *q;
|
const char *q;
|
||||||
|
|
||||||
if (check_params(buf, sizeof(buf), slirp_params, p) < 0) {
|
if (check_params(buf, sizeof(buf), slirp_params, p) < 0) {
|
||||||
@ -2268,14 +2406,29 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
|
|||||||
ret = -1;
|
ret = -1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
if (get_param_value(buf, sizeof(buf), "ip", p)) {
|
||||||
|
/* emulate legacy parameter */
|
||||||
|
vnet = qemu_malloc(strlen(buf) + strlen("/24") + 1);
|
||||||
|
strcpy(vnet, buf);
|
||||||
|
strcat(vnet, "/24");
|
||||||
|
}
|
||||||
|
if (get_param_value(buf, sizeof(buf), "net", p)) {
|
||||||
|
vnet = qemu_strdup(buf);
|
||||||
|
}
|
||||||
|
if (get_param_value(buf, sizeof(buf), "host", p)) {
|
||||||
|
vhost = qemu_strdup(buf);
|
||||||
|
}
|
||||||
if (get_param_value(buf, sizeof(buf), "hostname", p)) {
|
if (get_param_value(buf, sizeof(buf), "hostname", p)) {
|
||||||
pstrcpy(slirp_hostname, sizeof(slirp_hostname), buf);
|
vhostname = qemu_strdup(buf);
|
||||||
}
|
}
|
||||||
if (get_param_value(buf, sizeof(buf), "restrict", p)) {
|
if (get_param_value(buf, sizeof(buf), "restrict", p)) {
|
||||||
restricted = (buf[0] == 'y') ? 1 : 0;
|
restricted = (buf[0] == 'y') ? 1 : 0;
|
||||||
}
|
}
|
||||||
if (get_param_value(buf, sizeof(buf), "ip", p)) {
|
if (get_param_value(buf, sizeof(buf), "dhcpstart", p)) {
|
||||||
ip = qemu_strdup(buf);
|
vdhcp_start = qemu_strdup(buf);
|
||||||
|
}
|
||||||
|
if (get_param_value(buf, sizeof(buf), "dns", p)) {
|
||||||
|
vnamesrv = qemu_strdup(buf);
|
||||||
}
|
}
|
||||||
if (get_param_value(buf, sizeof(buf), "tftp", p)) {
|
if (get_param_value(buf, sizeof(buf), "tftp", p)) {
|
||||||
tftp_export = qemu_strdup(buf);
|
tftp_export = qemu_strdup(buf);
|
||||||
@ -2285,15 +2438,18 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
|
|||||||
}
|
}
|
||||||
if (get_param_value(buf, sizeof(buf), "smb", p)) {
|
if (get_param_value(buf, sizeof(buf), "smb", p)) {
|
||||||
smb_export = qemu_strdup(buf);
|
smb_export = qemu_strdup(buf);
|
||||||
|
if (get_param_value(buf, sizeof(buf), "smbserver", p)) {
|
||||||
|
vsmbsrv = qemu_strdup(buf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
q = p;
|
q = p;
|
||||||
while (1) {
|
while (1) {
|
||||||
config = qemu_malloc(sizeof(*config));
|
config = qemu_malloc(sizeof(*config));
|
||||||
if (!get_next_param_value(config->str, sizeof(config->str),
|
if (!get_next_param_value(config->str, sizeof(config->str),
|
||||||
"redir", &q)) {
|
"hostfwd", &q)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
config->flags = SLIRP_CFG_REDIR;
|
config->flags = SLIRP_CFG_HOSTFWD;
|
||||||
config->next = slirp_configs;
|
config->next = slirp_configs;
|
||||||
slirp_configs = config;
|
slirp_configs = config;
|
||||||
config = NULL;
|
config = NULL;
|
||||||
@ -2302,7 +2458,7 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
|
|||||||
while (1) {
|
while (1) {
|
||||||
config = qemu_malloc(sizeof(*config));
|
config = qemu_malloc(sizeof(*config));
|
||||||
if (!get_next_param_value(config->str, sizeof(config->str),
|
if (!get_next_param_value(config->str, sizeof(config->str),
|
||||||
"channel", &q)) {
|
"guestfwd", &q)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
config->flags = 0;
|
config->flags = 0;
|
||||||
@ -2312,23 +2468,29 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
|
|||||||
}
|
}
|
||||||
qemu_free(config);
|
qemu_free(config);
|
||||||
vlan->nb_host_devs++;
|
vlan->nb_host_devs++;
|
||||||
ret = net_slirp_init(mon, vlan, device, name, restricted, ip,
|
ret = net_slirp_init(mon, vlan, device, name, restricted, vnet, vhost,
|
||||||
tftp_export, bootfile, smb_export);
|
vhostname, tftp_export, bootfile, vdhcp_start,
|
||||||
qemu_free(ip);
|
vnamesrv, smb_export, vsmbsrv);
|
||||||
|
qemu_free(vnet);
|
||||||
|
qemu_free(vhost);
|
||||||
|
qemu_free(vhostname);
|
||||||
qemu_free(tftp_export);
|
qemu_free(tftp_export);
|
||||||
qemu_free(bootfile);
|
qemu_free(bootfile);
|
||||||
|
qemu_free(vdhcp_start);
|
||||||
|
qemu_free(vnamesrv);
|
||||||
qemu_free(smb_export);
|
qemu_free(smb_export);
|
||||||
|
qemu_free(vsmbsrv);
|
||||||
} else if (!strcmp(device, "channel")) {
|
} else if (!strcmp(device, "channel")) {
|
||||||
if (!slirp_inited) {
|
if (!slirp_inited) {
|
||||||
struct slirp_config_str *config;
|
struct slirp_config_str *config;
|
||||||
|
|
||||||
config = qemu_malloc(sizeof(*config));
|
config = qemu_malloc(sizeof(*config));
|
||||||
pstrcpy(config->str, sizeof(config->str), p);
|
pstrcpy(config->str, sizeof(config->str), p);
|
||||||
config->flags = 0;
|
config->flags = SLIRP_CFG_LEGACY;
|
||||||
config->next = slirp_configs;
|
config->next = slirp_configs;
|
||||||
slirp_configs = config;
|
slirp_configs = config;
|
||||||
} else {
|
} else {
|
||||||
vmchannel_init(mon, p);
|
slirp_guestfwd(mon, p, 1);
|
||||||
}
|
}
|
||||||
ret = 0;
|
ret = 0;
|
||||||
} else
|
} else
|
||||||
|
@ -749,10 +749,11 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
|
|||||||
"-net nic[,vlan=n][,macaddr=mac][,model=type][,name=str][,addr=str][,vectors=v]\n"
|
"-net nic[,vlan=n][,macaddr=mac][,model=type][,name=str][,addr=str][,vectors=v]\n"
|
||||||
" create a new Network Interface Card and connect it to VLAN 'n'\n"
|
" create a new Network Interface Card and connect it to VLAN 'n'\n"
|
||||||
#ifdef CONFIG_SLIRP
|
#ifdef CONFIG_SLIRP
|
||||||
"-net user[,vlan=n][,name=str][ip=netaddr][,restrict=y|n][,hostname=host]\n"
|
"-net user[,vlan=n][,name=str][,net=addr[/mask]][,host=addr][,restrict=y|n]\n"
|
||||||
" [,tftp=dir][,bootfile=f][,redir=rule][,channel=rule]"
|
" [,hostname=host][,dhcpstart=addr][,dns=addr][,tftp=dir][,bootfile=f]\n"
|
||||||
|
" [,hostfwd=rule][,guestfwd=rule]"
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
"[,smb=dir]\n"
|
"[,smb=dir[,smbserver=addr]]\n"
|
||||||
#endif
|
#endif
|
||||||
" connect the user mode network stack to VLAN 'n', configure its\n"
|
" connect the user mode network stack to VLAN 'n', configure its\n"
|
||||||
" DHCP server and enabled optional services\n"
|
" DHCP server and enabled optional services\n"
|
||||||
@ -819,8 +820,14 @@ Connect user mode stack to VLAN @var{n} (@var{n} = 0 is the default).
|
|||||||
@item name=@var{name}
|
@item name=@var{name}
|
||||||
Assign symbolic name for use in monitor commands.
|
Assign symbolic name for use in monitor commands.
|
||||||
|
|
||||||
@item ip=@var{netaddr}
|
@item net=@var{addr}[/@var{mask}]
|
||||||
Set IP network address the guest will see (default: 10.0.2.x).
|
Set IP network address the guest will see. Optionally specify the netmask,
|
||||||
|
either in the form a.b.c.d or as number of valid top-most bits. Default is
|
||||||
|
10.0.2.0/8.
|
||||||
|
|
||||||
|
@item host=@var{addr}
|
||||||
|
Specify the guest-visible address of the host. Default is the 2nd IP in the
|
||||||
|
guest network, i.e. x.x.x.2.
|
||||||
|
|
||||||
@item restrict=y|yes|n|no
|
@item restrict=y|yes|n|no
|
||||||
If this options is enabled, the guest will be isolated, i.e. it will not be
|
If this options is enabled, the guest will be isolated, i.e. it will not be
|
||||||
@ -830,12 +837,20 @@ to the outside. This option does not affect explicitly set forwarding rule.
|
|||||||
@item hostname=@var{name}
|
@item hostname=@var{name}
|
||||||
Specifies the client hostname reported by the builtin DHCP server.
|
Specifies the client hostname reported by the builtin DHCP server.
|
||||||
|
|
||||||
|
@item dhcpstart=@var{addr}
|
||||||
|
Specify the first of the 16 IPs the built-in DHCP server can assign. Default
|
||||||
|
is the 16th to 31st IP in the guest network, i.e. x.x.x.16 to x.x.x.31.
|
||||||
|
|
||||||
|
@item dns=@var{addr}
|
||||||
|
Specify the guest-visible address of the virtual nameserver. The address must
|
||||||
|
be different from the host address. Default is the 3rd IP in the guest network,
|
||||||
|
i.e. x.x.x.3.
|
||||||
|
|
||||||
@item tftp=@var{dir}
|
@item tftp=@var{dir}
|
||||||
When using the user mode network stack, activate a built-in TFTP
|
When using the user mode network stack, activate a built-in TFTP
|
||||||
server. The files in @var{dir} will be exposed as the root of a TFTP server.
|
server. The files in @var{dir} will be exposed as the root of a TFTP server.
|
||||||
The TFTP client on the guest must be configured in binary mode (use the command
|
The TFTP client on the guest must be configured in binary mode (use the command
|
||||||
@code{bin} of the Unix TFTP client). The host IP address on the guest is
|
@code{bin} of the Unix TFTP client).
|
||||||
10.0.2.2 by default.
|
|
||||||
|
|
||||||
@item bootfile=@var{file}
|
@item bootfile=@var{file}
|
||||||
When using the user mode network stack, broadcast @var{file} as the BOOTP
|
When using the user mode network stack, broadcast @var{file} as the BOOTP
|
||||||
@ -847,10 +862,11 @@ Example (using pxelinux):
|
|||||||
qemu -hda linux.img -boot n -net user,tftp=/path/to/tftp/files,bootfile=/pxelinux.0
|
qemu -hda linux.img -boot n -net user,tftp=/path/to/tftp/files,bootfile=/pxelinux.0
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
@item smb=@var{dir}
|
@item smb=@var{dir}[,smbserver=@var{addr}]
|
||||||
When using the user mode network stack, activate a built-in SMB
|
When using the user mode network stack, activate a built-in SMB
|
||||||
server so that Windows OSes can access to the host files in @file{@var{dir}}
|
server so that Windows OSes can access to the host files in @file{@var{dir}}
|
||||||
transparently.
|
transparently. The IP address of the SMB server can be set to @var{addr}. By
|
||||||
|
default the 4th IP in the guest network is used, i.e. x.x.x.4.
|
||||||
|
|
||||||
In the guest Windows OS, the line:
|
In the guest Windows OS, the line:
|
||||||
@example
|
@example
|
||||||
@ -865,19 +881,19 @@ Note that a SAMBA server must be installed on the host OS in
|
|||||||
@file{/usr/sbin/smbd}. QEMU was tested successfully with smbd versions from
|
@file{/usr/sbin/smbd}. QEMU was tested successfully with smbd versions from
|
||||||
Red Hat 9, Fedora Core 3 and OpenSUSE 11.x.
|
Red Hat 9, Fedora Core 3 and OpenSUSE 11.x.
|
||||||
|
|
||||||
@item redir=[tcp|udp]:@var{host-port}:[@var{guest-host}]:@var{guest-port}
|
@item hostfwd=[tcp|udp]:@var{hostport}:[@var{guestaddr}]:@var{guestport}
|
||||||
Redirect incoming TCP or UDP connections to the host port @var{host-port} to
|
Redirect incoming TCP or UDP connections to the host port @var{hostport} to
|
||||||
the guest @var{guest-host} on guest port @var{guest-port}. If @var{guest-host}
|
the guest IP address @var{guestaddr} on guest port @var{guestport}. If
|
||||||
is not specified, its value is 10.0.2.15 (default address given by the built-in
|
@var{guestaddr} is not specified, its value is x.x.x.15 (default first address
|
||||||
DHCP server). If no connection type is specified, TCP is used. This option can
|
given by the built-in DHCP server). If no connection type is specified, TCP is
|
||||||
be given multiple times.
|
used. This option can be given multiple times.
|
||||||
|
|
||||||
For example, to redirect host X11 connection from screen 1 to guest
|
For example, to redirect host X11 connection from screen 1 to guest
|
||||||
screen 0, use the following:
|
screen 0, use the following:
|
||||||
|
|
||||||
@example
|
@example
|
||||||
# on the host
|
# on the host
|
||||||
qemu -net user,redir=tcp:6001::6000 [...]
|
qemu -net user,hostfwd=tcp:6001::6000 [...]
|
||||||
# this host xterm should open in the guest X11 server
|
# this host xterm should open in the guest X11 server
|
||||||
xterm -display :1
|
xterm -display :1
|
||||||
@end example
|
@end example
|
||||||
@ -887,14 +903,14 @@ the guest, use the following:
|
|||||||
|
|
||||||
@example
|
@example
|
||||||
# on the host
|
# on the host
|
||||||
qemu -net user,redir=tcp:5555::23 [...]
|
qemu -net user,hostfwd=tcp:5555::23 [...]
|
||||||
telnet localhost 5555
|
telnet localhost 5555
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
Then when you use on the host @code{telnet localhost 5555}, you
|
Then when you use on the host @code{telnet localhost 5555}, you
|
||||||
connect to the guest telnet server.
|
connect to the guest telnet server.
|
||||||
|
|
||||||
@item channel=@var{port}:@var{dev}
|
@item guestfwd=[tcp]:@var{server}:@var{port}-@var{dev}
|
||||||
Forward guest TCP connections to port @var{port} on the host to character
|
Forward guest TCP connections to port @var{port} on the host to character
|
||||||
device @var{dev}. This option can be given multiple times.
|
device @var{dev}. This option can be given multiple times.
|
||||||
|
|
||||||
|
@ -5,8 +5,11 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void slirp_init(int restricted, const char *special_ip, const char *tftp_path,
|
void slirp_init(int restricted, struct in_addr vnetwork,
|
||||||
const char *bootfile);
|
struct in_addr vnetmask, struct in_addr vhost,
|
||||||
|
const char *vhostname, const char *tftp_path,
|
||||||
|
const char *bootfile, struct in_addr vdhcp_start,
|
||||||
|
struct in_addr vnameserver);
|
||||||
|
|
||||||
void slirp_select_fill(int *pnfds,
|
void slirp_select_fill(int *pnfds,
|
||||||
fd_set *readfds, fd_set *writefds, fd_set *xfds);
|
fd_set *readfds, fd_set *writefds, fd_set *xfds);
|
||||||
@ -19,18 +22,17 @@ void slirp_input(const uint8_t *pkt, int pkt_len);
|
|||||||
int slirp_can_output(void);
|
int slirp_can_output(void);
|
||||||
void slirp_output(const uint8_t *pkt, int pkt_len);
|
void slirp_output(const uint8_t *pkt, int pkt_len);
|
||||||
|
|
||||||
int slirp_redir_rm(int is_udp, int host_port);
|
int slirp_add_hostfwd(int is_udp, int host_port,
|
||||||
int slirp_redir(int is_udp, int host_port,
|
struct in_addr guest_addr, int guest_port);
|
||||||
struct in_addr guest_addr, int guest_port);
|
int slirp_remove_hostfwd(int is_udp, int host_port);
|
||||||
int slirp_add_exec(int do_pty, const void *args, int addr_low_byte,
|
|
||||||
|
int slirp_add_exec(int do_pty, const void *args, struct in_addr guest_addr,
|
||||||
int guest_port);
|
int guest_port);
|
||||||
|
|
||||||
extern char slirp_hostname[33];
|
|
||||||
|
|
||||||
void slirp_stats(void);
|
void slirp_stats(void);
|
||||||
void slirp_socket_recv(int addr_low_byte, int guest_port, const uint8_t *buf,
|
void slirp_socket_recv(struct in_addr guest_addr, int guest_port,
|
||||||
int size);
|
const uint8_t *buf, int size);
|
||||||
size_t slirp_socket_can_recv(int addr_low_byte, int guest_port);
|
size_t slirp_socket_can_recv(struct in_addr guest_addr, int guest_port);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,7 @@ extern int ppp_exit;
|
|||||||
extern int tcp_keepintvl;
|
extern int tcp_keepintvl;
|
||||||
extern uint8_t client_ethaddr[6];
|
extern uint8_t client_ethaddr[6];
|
||||||
extern int slirp_restrict;
|
extern int slirp_restrict;
|
||||||
|
extern char slirp_hostname[33];
|
||||||
extern char *tftp_prefix;
|
extern char *tftp_prefix;
|
||||||
extern char *bootp_filename;
|
extern char *bootp_filename;
|
||||||
|
|
||||||
|
@ -173,12 +173,14 @@ static void slirp_cleanup(void)
|
|||||||
static void slirp_state_save(QEMUFile *f, void *opaque);
|
static void slirp_state_save(QEMUFile *f, void *opaque);
|
||||||
static int slirp_state_load(QEMUFile *f, void *opaque, int version_id);
|
static int slirp_state_load(QEMUFile *f, void *opaque, int version_id);
|
||||||
|
|
||||||
void slirp_init(int restricted, const char *special_ip, const char *tftp_path,
|
void slirp_init(int restricted, struct in_addr vnetwork,
|
||||||
const char *bootfile)
|
struct in_addr vnetmask, struct in_addr vhost,
|
||||||
|
const char *vhostname, const char *tftp_path,
|
||||||
|
const char *bootfile, struct in_addr vdhcp_start,
|
||||||
|
struct in_addr vnameserver)
|
||||||
{
|
{
|
||||||
// debug_init("/tmp/slirp.log", DEBUG_DEFAULT);
|
// debug_init("/tmp/slirp.log", DEBUG_DEFAULT);
|
||||||
|
|
||||||
struct in_addr special_addr = { .s_addr = htonl(0x0a000200) };
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
WSADATA Data;
|
WSADATA Data;
|
||||||
|
|
||||||
@ -203,8 +205,11 @@ void slirp_init(int restricted, const char *special_ip, const char *tftp_path,
|
|||||||
fprintf (stderr, "Warning: No DNS servers found\n");
|
fprintf (stderr, "Warning: No DNS servers found\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (special_ip) {
|
vnetwork_addr = vnetwork;
|
||||||
inet_aton(special_ip, &special_addr);
|
vnetwork_mask = vnetmask;
|
||||||
|
vhost_addr = vhost;
|
||||||
|
if (vhostname) {
|
||||||
|
pstrcpy(slirp_hostname, sizeof(slirp_hostname), vhostname);
|
||||||
}
|
}
|
||||||
qemu_free(tftp_prefix);
|
qemu_free(tftp_prefix);
|
||||||
tftp_prefix = NULL;
|
tftp_prefix = NULL;
|
||||||
@ -216,12 +221,9 @@ void slirp_init(int restricted, const char *special_ip, const char *tftp_path,
|
|||||||
if (bootfile) {
|
if (bootfile) {
|
||||||
bootp_filename = qemu_strdup(bootfile);
|
bootp_filename = qemu_strdup(bootfile);
|
||||||
}
|
}
|
||||||
|
vdhcp_startaddr = vdhcp_start;
|
||||||
|
vnameserver_addr = vnameserver;
|
||||||
|
|
||||||
vnetwork_addr = special_addr;
|
|
||||||
vnetwork_mask.s_addr = htonl(0xffffff00);
|
|
||||||
vhost_addr.s_addr = special_addr.s_addr | htonl(2);
|
|
||||||
vdhcp_startaddr.s_addr = special_addr.s_addr | htonl(15);
|
|
||||||
vnameserver_addr.s_addr = special_addr.s_addr | htonl(3);
|
|
||||||
getouraddr();
|
getouraddr();
|
||||||
register_savevm("slirp", 0, 1, slirp_state_save, slirp_state_load, NULL);
|
register_savevm("slirp", 0, 1, slirp_state_save, slirp_state_load, NULL);
|
||||||
}
|
}
|
||||||
@ -755,7 +757,7 @@ void if_encap(const uint8_t *ip_data, int ip_data_len)
|
|||||||
/* Unlistens a redirection
|
/* Unlistens a redirection
|
||||||
*
|
*
|
||||||
* Return value: number of redirs removed */
|
* Return value: number of redirs removed */
|
||||||
int slirp_redir_rm(int is_udp, int host_port)
|
int slirp_remove_hostfwd(int is_udp, int host_port)
|
||||||
{
|
{
|
||||||
struct socket *so;
|
struct socket *so;
|
||||||
struct socket *head = (is_udp ? &udb : &tcb);
|
struct socket *head = (is_udp ? &udb : &tcb);
|
||||||
@ -775,8 +777,8 @@ int slirp_redir_rm(int is_udp, int host_port)
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
int slirp_redir(int is_udp, int host_port,
|
int slirp_add_hostfwd(int is_udp, int host_port,
|
||||||
struct in_addr guest_addr, int guest_port)
|
struct in_addr guest_addr, int guest_port)
|
||||||
{
|
{
|
||||||
if (!guest_addr.s_addr) {
|
if (!guest_addr.s_addr) {
|
||||||
guest_addr = vdhcp_startaddr;
|
guest_addr = vdhcp_startaddr;
|
||||||
@ -793,13 +795,13 @@ int slirp_redir(int is_udp, int host_port,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int slirp_add_exec(int do_pty, const void *args, int addr_low_byte,
|
int slirp_add_exec(int do_pty, const void *args, struct in_addr guest_addr,
|
||||||
int guest_port)
|
int guest_port)
|
||||||
{
|
{
|
||||||
struct in_addr guest_addr = {
|
if (!guest_addr.s_addr) {
|
||||||
.s_addr = vnetwork_addr.s_addr | htonl(addr_low_byte)
|
guest_addr.s_addr =
|
||||||
};
|
vnetwork_addr.s_addr | (htonl(0x0204) & ~vnetwork_mask.s_addr);
|
||||||
|
}
|
||||||
if ((guest_addr.s_addr & vnetwork_mask.s_addr) != vnetwork_addr.s_addr ||
|
if ((guest_addr.s_addr & vnetwork_mask.s_addr) != vnetwork_addr.s_addr ||
|
||||||
guest_addr.s_addr == vhost_addr.s_addr ||
|
guest_addr.s_addr == vhost_addr.s_addr ||
|
||||||
guest_addr.s_addr == vnameserver_addr.s_addr) {
|
guest_addr.s_addr == vnameserver_addr.s_addr) {
|
||||||
@ -833,11 +835,8 @@ slirp_find_ctl_socket(struct in_addr guest_addr, int guest_port)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t slirp_socket_can_recv(int addr_low_byte, int guest_port)
|
size_t slirp_socket_can_recv(struct in_addr guest_addr, int guest_port)
|
||||||
{
|
{
|
||||||
struct in_addr guest_addr = {
|
|
||||||
.s_addr = vnetwork_addr.s_addr | htonl(addr_low_byte)
|
|
||||||
};
|
|
||||||
struct iovec iov[2];
|
struct iovec iov[2];
|
||||||
struct socket *so;
|
struct socket *so;
|
||||||
|
|
||||||
@ -855,13 +854,10 @@ size_t slirp_socket_can_recv(int addr_low_byte, int guest_port)
|
|||||||
return sopreprbuf(so, iov, NULL);
|
return sopreprbuf(so, iov, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void slirp_socket_recv(int addr_low_byte, int guest_port, const uint8_t *buf,
|
void slirp_socket_recv(struct in_addr guest_addr, int guest_port,
|
||||||
int size)
|
const uint8_t *buf, int size)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct in_addr guest_addr = {
|
|
||||||
.s_addr = vnetwork_addr.s_addr | htonl(addr_low_byte)
|
|
||||||
};
|
|
||||||
struct socket *so = slirp_find_ctl_socket(guest_addr, guest_port);
|
struct socket *so = slirp_find_ctl_socket(guest_addr, guest_port);
|
||||||
|
|
||||||
if (!so)
|
if (!so)
|
||||||
|
Loading…
Reference in New Issue
Block a user