aboutsummaryrefslogtreecommitdiff
path: root/net/slirp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/slirp.c')
-rw-r--r--net/slirp.c123
1 files changed, 94 insertions, 29 deletions
diff --git a/net/slirp.c b/net/slirp.c
index 9657e86..c627a9d 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -258,11 +258,13 @@ static void net_slirp_register_poll_sock(slirp_os_socket fd, void *opaque)
{
#ifdef WIN32
AioContext *ctxt = qemu_get_aio_context();
+ g_autofree char *msg = NULL;
if (WSAEventSelect(fd, event_notifier_get_handle(&ctxt->notifier),
FD_READ | FD_ACCEPT | FD_CLOSE |
FD_CONNECT | FD_WRITE | FD_OOB) != 0) {
- error_setg_win32(&error_warn, WSAGetLastError(), "failed to WSAEventSelect()");
+ msg = g_win32_error_message(WSAGetLastError());
+ warn_report("failed to WSAEventSelect(): %s", msg);
}
#endif
}
@@ -270,8 +272,11 @@ static void net_slirp_register_poll_sock(slirp_os_socket fd, void *opaque)
static void net_slirp_unregister_poll_sock(slirp_os_socket fd, void *opaque)
{
#ifdef WIN32
+ g_autofree char *msg = NULL;
+
if (WSAEventSelect(fd, NULL, 0) != 0) {
- error_setg_win32(&error_warn, WSAGetLastError(), "failed to WSAEventSelect()");
+ msg = g_win32_error_message(WSAGetLastError());
+ warn_report("failed to WSAEventSelect(): %s", msg);
}
#endif
}
@@ -727,6 +732,7 @@ static SlirpState *slirp_lookup(Monitor *mon, const char *id)
void hmp_hostfwd_remove(Monitor *mon, const QDict *qdict)
{
+ /* TODO: support removing unix fwd */
struct sockaddr_in host_addr = {
.sin_family = AF_INET,
.sin_addr = {
@@ -795,12 +801,13 @@ void hmp_hostfwd_remove(Monitor *mon, const QDict *qdict)
static int slirp_hostfwd(SlirpState *s, const char *redir_str, Error **errp)
{
- struct sockaddr_in host_addr = {
- .sin_family = AF_INET,
- .sin_addr = {
- .s_addr = INADDR_ANY,
- },
- };
+ union {
+ struct sockaddr_in in;
+#if !defined(WIN32) && SLIRP_CHECK_VERSION(4, 7, 0)
+ struct sockaddr_un un;
+#endif
+ } host_addr = {0};
+
struct sockaddr_in guest_addr = {
.sin_family = AF_INET,
.sin_addr = {
@@ -811,9 +818,13 @@ static int slirp_hostfwd(SlirpState *s, const char *redir_str, Error **errp)
int host_port, guest_port;
const char *p;
char buf[256];
- int is_udp;
+ int is_udp = 0;
+#if !defined(WIN32) && SLIRP_CHECK_VERSION(4, 7, 0)
+ int is_unix = 0;
+#endif
const char *end;
const char *fail_reason = "Unknown reason";
+ socklen_t host_addr_size;
p = redir_str;
if (!p || get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
@@ -824,30 +835,83 @@ static int slirp_hostfwd(SlirpState *s, const char *redir_str, Error **errp)
is_udp = 0;
} else if (!strcmp(buf, "udp")) {
is_udp = 1;
- } else {
- fail_reason = "Bad protocol name";
- goto fail_syntax;
}
-
- if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
- fail_reason = "Missing : separator";
- goto fail_syntax;
+#if !defined(WIN32) && SLIRP_CHECK_VERSION(4, 7, 0)
+ else if (!strcmp(buf, "unix")) {
+ is_unix = 1;
}
- if (buf[0] != '\0' && !inet_aton(buf, &host_addr.sin_addr)) {
- fail_reason = "Bad host address";
+#endif
+ else {
+ fail_reason = "Bad protocol name";
goto fail_syntax;
}
- if (get_str_sep(buf, sizeof(buf), &p, '-') < 0) {
- fail_reason = "Bad host port separator";
- goto fail_syntax;
- }
- err = qemu_strtoi(buf, &end, 0, &host_port);
- if (err || host_port < 0 || host_port > 65535) {
- fail_reason = "Bad host port";
- goto fail_syntax;
+#if !defined(WIN32) && SLIRP_CHECK_VERSION(4, 7, 0)
+ if (is_unix) {
+ if (get_str_sep(buf, sizeof(buf), &p, '-') < 0) {
+ fail_reason = "Missing - separator";
+ goto fail_syntax;
+ }
+ if (buf[0] == '\0') {
+ fail_reason = "Missing unix socket path";
+ goto fail_syntax;
+ }
+ if (buf[0] != '/') {
+ fail_reason = "unix socket path must be absolute";
+ goto fail_syntax;
+ }
+
+ size_t path_len = strlen(buf);
+ if (path_len > sizeof(host_addr.un.sun_path) - 1) {
+ fail_reason = "Unix socket path is too long";
+ goto fail_syntax;
+ }
+
+ struct stat st;
+ if (stat(buf, &st) == 0) {
+ if (!S_ISSOCK(st.st_mode)) {
+ fail_reason = "file exists and it's not unix socket";
+ goto fail_syntax;
+ }
+
+ if (unlink(buf) < 0) {
+ error_setg_errno(errp, errno, "Failed to unlink '%s'", buf);
+ goto fail_syntax;
+ }
+ }
+ host_addr.un.sun_family = AF_UNIX;
+ memcpy(host_addr.un.sun_path, buf, path_len);
+ host_addr_size = sizeof(host_addr.un);
+ } else
+#endif
+ {
+ host_addr.in.sin_family = AF_INET;
+ host_addr.in.sin_addr.s_addr = INADDR_ANY;
+
+ if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
+ fail_reason = "Missing : separator";
+ goto fail_syntax;
+ }
+
+ if (buf[0] != '\0' && !inet_aton(buf, &host_addr.in.sin_addr)) {
+ fail_reason = "Bad host address";
+ goto fail_syntax;
+ }
+
+ if (get_str_sep(buf, sizeof(buf), &p, '-') < 0) {
+ fail_reason = "Bad host port separator";
+ goto fail_syntax;
+ }
+
+ err = qemu_strtoi(buf, &end, 0, &host_port);
+ if (err || host_port < 0 || host_port > 65535) {
+ fail_reason = "Bad host port";
+ goto fail_syntax;
+ }
+
+ host_addr.in.sin_port = htons(host_port);
+ host_addr_size = sizeof(host_addr.in);
}
- host_addr.sin_port = htons(host_port);
if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
fail_reason = "Missing guest address";
@@ -867,12 +931,13 @@ static int slirp_hostfwd(SlirpState *s, const char *redir_str, Error **errp)
#if SLIRP_CHECK_VERSION(4, 5, 0)
err = slirp_add_hostxfwd(s->slirp,
- (struct sockaddr *) &host_addr, sizeof(host_addr),
+ (struct sockaddr *) &host_addr, host_addr_size,
(struct sockaddr *) &guest_addr, sizeof(guest_addr),
is_udp ? SLIRP_HOSTFWD_UDP : 0);
#else
+ (void) host_addr_size;
err = slirp_add_hostfwd(s->slirp, is_udp,
- host_addr.sin_addr, host_port,
+ host_addr.in.sin_addr, host_port,
guest_addr.sin_addr, guest_port);
#endif