diff options
author | B. Scott Michel <scooter.phd@gmail.com> | 2024-09-16 09:14:32 -0700 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2024-09-26 03:04:25 +0200 |
commit | 72f85005a2307fd0961543e3cea861ad7a4d201e (patch) | |
tree | aaea4bf5c09fd87901712517113ff624f4cc44f4 /src | |
parent | 5e97a93bf0599037de37d45c33d4cdb902a5264e (diff) | |
download | slirp-72f85005a2307fd0961543e3cea861ad7a4d201e.zip slirp-72f85005a2307fd0961543e3cea861ad7a4d201e.tar.gz slirp-72f85005a2307fd0961543e3cea861ad7a4d201e.tar.bz2 |
socket abstraction: slirp_os_socket
Use a typedef to abstract socket identifiers because Windows just has to
be different (SOCKET type.) Moreover, SOCKET on Win64 is 64-bits and
generates copious type slicing warnings.
Other related changes:
- Explicitly cast curtime's assignment to unsigned int to tamp down on
type slicing warning.
- Ensure that errno.h is always included. Important for Windows, which
would otherwise #define errno as WSAGetLastError(); errno.h #define-s
errno as a function, i.e., "*errno()".
- Export slirp_inet_aton() utility function for Win32/64.
- tcpx_listen()
- WSASetLastError() unnecessary.
- Use have_valid_socket() to check socket in error cleanup code
(vs. "s >= 0").
Diffstat (limited to 'src')
-rw-r--r-- | src/ip6_icmp.c | 4 | ||||
-rw-r--r-- | src/ip_icmp.c | 8 | ||||
-rw-r--r-- | src/libslirp.h | 40 | ||||
-rw-r--r-- | src/misc.c | 38 | ||||
-rw-r--r-- | src/slirp.c | 14 | ||||
-rw-r--r-- | src/slirp.h | 19 | ||||
-rw-r--r-- | src/socket.c | 30 | ||||
-rw-r--r-- | src/socket.h | 9 | ||||
-rw-r--r-- | src/tcp_subr.c | 27 | ||||
-rw-r--r-- | src/tftp.c | 13 | ||||
-rw-r--r-- | src/udp.c | 18 | ||||
-rw-r--r-- | src/udp.h | 10 | ||||
-rw-r--r-- | src/udp6.c | 8 | ||||
-rw-r--r-- | src/util.c | 106 | ||||
-rw-r--r-- | src/util.h | 84 |
15 files changed, 266 insertions, 162 deletions
diff --git a/src/ip6_icmp.c b/src/ip6_icmp.c index 3a5878f..2f48362 100644 --- a/src/ip6_icmp.c +++ b/src/ip6_icmp.c @@ -62,7 +62,7 @@ static int icmp6_send(struct socket *so, struct mbuf *m, int hlen) #endif so->s = slirp_socket(AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6); - if (so->s == -1) { + if (not_valid_socket(so->s)) { if (errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT || errno == EACCES) { @@ -71,7 +71,7 @@ static int icmp6_send(struct socket *so, struct mbuf *m, int hlen) so->s = slirp_socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); } } - if (so->s == -1) { + if (not_valid_socket(so->s)) { return -1; } so->slirp->cb->register_poll_fd(so->s, so->slirp->opaque); diff --git a/src/ip_icmp.c b/src/ip_icmp.c index 74524fd..b6b0fab 100644 --- a/src/ip_icmp.c +++ b/src/ip_icmp.c @@ -110,7 +110,7 @@ static int icmp_send(struct socket *so, struct mbuf *m, int hlen) #endif so->s = slirp_socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP); - if (so->s == -1) { + if (not_valid_socket(so->s)) { if (errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT || errno == EACCES) { @@ -119,7 +119,7 @@ static int icmp_send(struct socket *so, struct mbuf *m, int hlen) so->s = slirp_socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); } } - if (so->s == -1) { + if (not_valid_socket(so->s)) { return -1; } so->slirp->cb->register_poll_fd(so->s, so->slirp->opaque); @@ -127,7 +127,7 @@ static int icmp_send(struct socket *so, struct mbuf *m, int hlen) if (slirp_bind_outbound(so, AF_INET) != 0) { // bind failed - close socket closesocket(so->s); - so->s = -1; + so->s = SLIRP_INVALID_SOCKET; return -1; } @@ -222,7 +222,7 @@ void icmp_input(struct mbuf *m, int hlen) /* We could not send this as ICMP, try to send it on UDP echo * service (7), wishfully hoping that it is open there. */ - if (udp_attach(so, AF_INET) == -1) { + if (not_valid_socket(udp_attach(so, AF_INET))) { DEBUG_MISC("icmp_input udp_attach errno = %d-%s", errno, strerror(errno)); sofree(so); diff --git a/src/libslirp.h b/src/libslirp.h index d36c601..4a68cc4 100644 --- a/src/libslirp.h +++ b/src/libslirp.h @@ -8,9 +8,12 @@ #ifdef _WIN32 #include <winsock2.h> +#include <windows.h> #include <ws2tcpip.h> #include <in6addr.h> #include <basetsd.h> +#include <errno.h> + typedef SSIZE_T slirp_ssize_t; #ifdef LIBSLIRP_STATIC # define SLIRP_EXPORT @@ -33,6 +36,28 @@ typedef ssize_t slirp_ssize_t; extern "C" { #endif +/* Socket abstraction:*/ + +#if !defined(_WIN32) +/* Traditional Unix socket. */ +typedef int slirp_os_socket; +#define SLIRP_INVALID_SOCKET (-1) +#define SLIRP_PRIfd "d" +#else +/* Windows: Win64 is a LLP64 platform, sizeof(int) < sizeof(long long) == sizeof(void *). + * + * Windows likes to pass HANDLE types around, which are pointers (aka unsigned long longs), + * which cannot be represented as ints. And, MS, in its infinite wisdom, decided to use + * a SOCKET handle instead of an int for socket library calls. */ +typedef SOCKET slirp_os_socket; +#define SLIRP_INVALID_SOCKET INVALID_SOCKET +#if defined(_WIN64) +# define SLIRP_PRIfd "llx" +#else +# define SLIRP_PRIfd "x" +#endif +#endif + /* Opaque structure containing the slirp state */ typedef struct Slirp Slirp; @@ -52,7 +77,7 @@ typedef slirp_ssize_t (*SlirpWriteCb)(const void *buf, size_t len, void *opaque) /* Timer callback */ typedef void (*SlirpTimerCb)(void *opaque); /* Callback for libslirp to register polling callbacks */ -typedef int (*SlirpAddPollCb)(int fd, int events, void *opaque); +typedef int (*SlirpAddPollCb)(slirp_os_socket fd, int events, void *opaque); /* Callback for libslirp to get polling result */ typedef int (*SlirpGetREventsCb)(int idx, void *opaque); @@ -89,9 +114,9 @@ typedef struct SlirpCb { /* Modify a timer to expire at @expire_time (ms) */ void (*timer_mod)(void *timer, int64_t expire_time, void *opaque); /* Register a fd for future polling */ - void (*register_poll_fd)(int fd, void *opaque); + void (*register_poll_fd)(slirp_os_socket fd, void *opaque); /* Unregister a fd */ - void (*unregister_poll_fd)(int fd, void *opaque); + void (*unregister_poll_fd)(slirp_os_socket fd, void *opaque); /* Kick the io-thread, to signal that new events may be processed because some TCP buffer * can now receive more data, i.e. slirp_socket_can_recv will return 1. */ void (*notify)(void *opaque); @@ -337,6 +362,15 @@ int slirp_state_load(Slirp *s, int version_id, SlirpReadCb read_cb, SLIRP_EXPORT const char *slirp_version_string(void); +#if defined(_WIN32) +/* Windows utility functions: */ + +/* inet_aton() replacement that uses inet_pton(). Eliminates the dreaded + * winsock2 deprecation messages. */ +SLIRP_EXPORT +int slirp_inet_aton(const char *cp, struct in_addr *ia); +#endif + #ifdef __cplusplus } /* extern "C" */ #endif @@ -77,7 +77,7 @@ int remove_guestfwd(struct gfwd_list **ex_ptr, struct in_addr addr, int port) return -1; } -static int slirp_socketpair_with_oob(int sv[2]) +static int slirp_socketpair_with_oob(slirp_os_socket sv[2]) { struct sockaddr_in addr = { .sin_family = AF_INET, @@ -85,18 +85,19 @@ static int slirp_socketpair_with_oob(int sv[2]) .sin_addr.s_addr = htonl(INADDR_LOOPBACK), }; socklen_t addrlen = sizeof(addr); - int ret, s; + int ret; + slirp_os_socket s; - sv[1] = -1; + sv[1] = SLIRP_INVALID_SOCKET; s = slirp_socket(AF_INET, SOCK_STREAM, 0); - if (s < 0 || bind(s, (struct sockaddr *)&addr, addrlen) < 0 || + if (not_valid_socket(s) || bind(s, (struct sockaddr *)&addr, addrlen) < 0 || listen(s, 1) < 0 || getsockname(s, (struct sockaddr *)&addr, &addrlen) < 0) { goto err; } sv[1] = slirp_socket(AF_INET, SOCK_STREAM, 0); - if (sv[1] < 0) { + if (not_valid_socket(sv[1])) { goto err; } /* @@ -123,7 +124,7 @@ static int slirp_socketpair_with_oob(int sv[2]) err: g_critical("slirp_socketpair(): %s", strerror(errno)); - if (s >= 0) { + if (have_valid_socket(s)) { closesocket(s); } if (sv[1] >= 0) { @@ -144,6 +145,10 @@ static void fork_exec_child_setup(gpointer data) /* POSIX is obnoxious about SIGCHLD specifically across exec() */ signal(SIGCHLD, SIG_DFL); +#else +#ifdef GLIB_UNUSED_PARAM + GLIB_UNUSED_PARAM(data); +#endif #endif } @@ -209,7 +214,8 @@ int fork_exec(struct socket *so, const char *ex) GError *err = NULL; gint argc = 0; gchar **argv = NULL; - int opt, sp[2]; + int opt; + slirp_os_socket sp[2]; DEBUG_CALL("fork_exec"); DEBUG_ARG("so = %p", so); @@ -243,7 +249,7 @@ int fork_exec(struct socket *so, const char *ex) closesocket(sp[1]); slirp_socket_set_fast_reuse(so->s); opt = 1; - setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); + setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, (const void *) &opt, sizeof(int)); slirp_set_nonblock(so->s); so->slirp->cb->register_poll_fd(so->s, so->slirp->opaque); return 1; @@ -267,7 +273,7 @@ int open_unix(struct socket *so, const char *unixpath) } s = slirp_socket(PF_UNIX, SOCK_STREAM, 0); - if (s < 0) { + if (not_valid_socket(s)) { g_critical("open_unix(): %s", strerror(errno)); return 0; } @@ -284,10 +290,15 @@ int open_unix(struct socket *so, const char *unixpath) return 1; #else +#ifdef GLIB_UNUSED_PARAM + GLIB_UNUSED_PARAM(so); + GLIB_UNUSED_PARAM(unixpath); +#endif g_assert_not_reached(); #endif } +SLIRP_EXPORT char *slirp_connection_info(Slirp *slirp) { GString *str = g_string_new(NULL); @@ -334,7 +345,7 @@ char *slirp_connection_info(Slirp *slirp) dst_port = so->so_fport; } slirp_fmt0(buf, sizeof(buf), " TCP[%s]", state); - g_string_append_printf(str, "%-19s %3d %15s %5d ", buf, so->s, + g_string_append_printf(str, "%-19s %3"SLIRP_PRIfd" %15s %5d ", buf, so->s, src.sin_addr.s_addr ? inet_ntop(AF_INET, &src.sin_addr, addr, sizeof(addr)) : "*", ntohs(src.sin_port)); @@ -359,7 +370,7 @@ char *slirp_connection_info(Slirp *slirp) dst_addr = so->so_faddr; dst_port = so->so_fport; } - g_string_append_printf(str, "%-19s %3d %15s %5d ", buf, so->s, + g_string_append_printf(str, "%-19s %3"SLIRP_PRIfd" %15s %5d ", buf, so->s, src.sin_addr.s_addr ? inet_ntop(AF_INET, &src.sin_addr, addr, sizeof(addr)) : "*", ntohs(src.sin_port)); @@ -374,7 +385,7 @@ char *slirp_connection_info(Slirp *slirp) (so->so_expire - curtime) / 1000); src.sin_addr = so->so_laddr; dst_addr = so->so_faddr; - g_string_append_printf(str, "%-19s %3d %15s - ", buf, so->s, + g_string_append_printf(str, "%-19s %3"SLIRP_PRIfd" %15s - ", buf, so->s, src.sin_addr.s_addr ? inet_ntop(AF_INET, &src.sin_addr, addr, sizeof(addr)) : "*"); g_string_append_printf(str, "%15s - %5d %5d\n", @@ -385,6 +396,7 @@ char *slirp_connection_info(Slirp *slirp) return g_string_free(str, FALSE); } +SLIRP_EXPORT char *slirp_neighbor_info(Slirp *slirp) { GString *str = g_string_new(NULL); @@ -430,7 +442,7 @@ char *slirp_neighbor_info(Slirp *slirp) int slirp_bind_outbound(struct socket *so, unsigned short af) { int ret = 0; - struct sockaddr *addr = NULL; + const struct sockaddr *addr = NULL; int addr_size = 0; if (af == AF_INET && so->slirp->outbound_addr != NULL) { diff --git a/src/slirp.c b/src/slirp.c index fd68f63..9f4c49e 100644 --- a/src/slirp.c +++ b/src/slirp.c @@ -812,7 +812,7 @@ void slirp_pollfds_fill(Slirp *slirp, uint32_t *timeout, * NOFDREF can include still connecting to local-host, * newly socreated() sockets etc. Don't want to select these. */ - if (so->so_state & SS_NOFDREF || so->s == -1) { + if (so->so_state & SS_NOFDREF || not_valid_socket(so->s)) { continue; } @@ -931,7 +931,7 @@ void slirp_pollfds_poll(Slirp *slirp, int select_error, struct socket *so, *so_next; int ret; - curtime = slirp->cb->clock_get_ns(slirp->opaque) / SCALE_MS; + curtime = (unsigned int) (slirp->cb->clock_get_ns(slirp->opaque) / SCALE_MS); /* * See if anything has timed out @@ -965,7 +965,7 @@ void slirp_pollfds_poll(Slirp *slirp, int select_error, revents = get_revents(so->pollfds_idx, opaque); } - if (so->so_state & SS_NOFDREF || so->s == -1) { + if (so->so_state & SS_NOFDREF || not_valid_socket(so->s)) { continue; } @@ -1074,7 +1074,7 @@ void slirp_pollfds_poll(Slirp *slirp, int select_error, revents = get_revents(so->pollfds_idx, opaque); } - if (so->s != -1 && + if (have_valid_socket(so->s) && (revents & (SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR))) { sorecvfrom(so); } @@ -1093,7 +1093,7 @@ void slirp_pollfds_poll(Slirp *slirp, int select_error, revents = get_revents(so->pollfds_idx, opaque); } - if (so->s != -1 && + if (have_valid_socket(so->s) && (revents & (SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR))) { if (so->so_type == IPPROTO_IPV6 || so->so_type == IPPROTO_ICMPV6) icmp6_receive(so); @@ -1547,14 +1547,14 @@ int slirp_remove_guestfwd(Slirp *slirp, struct in_addr guest_addr, slirp_ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags) { - if (so->s == -1 && so->guestfwd) { + if (not_valid_socket(so->s) && so->guestfwd) { /* XXX this blocks entire thread. Rewrite to use * qemu_chr_fe_write and background I/O callbacks */ so->guestfwd->write_cb(buf, len, so->guestfwd->opaque); return len; } - if (so->s == -1) { + if (not_valid_socket(so->s)) { /* * This should in theory not happen but it is hard to be * sure because some code paths will end up with so->s == -1 diff --git a/src/slirp.h b/src/slirp.h index 2715353..e28d496 100644 --- a/src/slirp.h +++ b/src/slirp.h @@ -3,11 +3,19 @@ #define SLIRP_H #ifdef _WIN32 +/* TARGET_WINVER defined on the compiler command line? */ +#if defined(TARGET_WINVER) && !defined(WINVER) +# define WINVER TARGET_WINVER +/* Default WINVER to Windows 7 API, same as glib. */ +#elif !defined(WINVER) +# define WINVER 0x0601 +#endif -/* as defined in sdkddkver.h */ -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0601 /* Windows 7 */ +/* Ensure that _WIN32_WINNT matches WINVER */ +#if defined(WINVER) && !defined(_WIN32_WINNT) +#define _WIN32_WINNT WINVER #endif + /* reduces the number of implicitly included headers */ #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN @@ -19,6 +27,11 @@ #include <sys/timeb.h> #include <iphlpapi.h> +/* Paranoia includes: */ +#include <errno.h> +#include <stdbool.h> +#include <io.h> + #else #define O_BINARY 0 #endif diff --git a/src/socket.c b/src/socket.c index c426be9..09e310e 100644 --- a/src/socket.c +++ b/src/socket.c @@ -16,8 +16,8 @@ static void sofcantrcvmore(struct socket *so); static void sofcantsendmore(struct socket *so); struct socket *solookup(struct socket **last, struct socket *head, - struct sockaddr_storage *lhost, - struct sockaddr_storage *fhost) + const struct sockaddr_storage *lhost, + const struct sockaddr_storage *fhost) { struct socket *so = *last; @@ -50,8 +50,8 @@ struct socket *socreate(Slirp *slirp, int type) memset(so, 0, sizeof(struct socket)); so->so_type = type; so->so_state = SS_NOFDREF; - so->s = -1; - so->s_aux = -1; + so->s = SLIRP_INVALID_SOCKET; + so->s_aux = SLIRP_INVALID_SOCKET; so->slirp = slirp; so->pollfds_idx = -1; @@ -61,7 +61,7 @@ struct socket *socreate(Slirp *slirp, int type) /* * Remove references to so from the given message queue. */ -static void soqfree(struct socket *so, struct slirp_quehead *qh) +static void soqfree(const struct socket *so, struct slirp_quehead *qh) { struct mbuf *ifq; @@ -84,7 +84,7 @@ void sofree(struct socket *so) { Slirp *slirp = so->slirp; - if (so->s_aux != -1) { + if (have_valid_socket(so->s_aux)) { closesocket(so->s_aux); } @@ -797,7 +797,8 @@ struct socket *tcpx_listen(Slirp *slirp, int flags) { struct socket *so; - int s, opt = 1; + slirp_os_socket s; + int opt = 1; socklen_t addrlen; DEBUG_CALL("tcpx_listen"); @@ -863,22 +864,19 @@ struct socket *tcpx_listen(Slirp *slirp, sockaddr_copy(&so->lhost.sa, sizeof(so->lhost), laddr, laddrlen); s = slirp_socket(haddr->sa_family, SOCK_STREAM, 0); - if ((s < 0) || + if ((not_valid_socket(s)) || (haddr->sa_family == AF_INET6 && slirp_socket_set_v6only(s, (flags & SS_HOSTFWD_V6ONLY) != 0) < 0) || (slirp_socket_set_fast_reuse(s) < 0) || (bind(s, haddr, haddrlen) < 0) || (listen(s, 1) < 0)) { int tmperrno = errno; /* Don't clobber the real reason we failed */ - if (s >= 0) { + if (have_valid_socket(s)) { closesocket(s); } sofree(so); /* Restore the real errno */ -#ifdef _WIN32 - WSASetLastError(tmperrno); -#else errno = tmperrno; -#endif + return NULL; } setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); @@ -1091,7 +1089,7 @@ void sotranslate_accept(struct socket *so) * this source port by binding to port 0 so that the OS allocates a * port for us. If this fails, we fall back to choosing a random port * with a random number generator. */ - int s; + slirp_os_socket s; struct sockaddr_in in_addr; struct sockaddr_in6 in6_addr; socklen_t in_addr_len; @@ -1112,7 +1110,7 @@ void sotranslate_accept(struct socket *so) g_assert_not_reached(); break; } - if (s < 0) { + if (not_valid_socket(s)) { g_error("Ephemeral slirp_socket() allocation failed"); goto unix2inet_cont; } @@ -1155,7 +1153,7 @@ unix2inet_cont: g_assert_not_reached(); break; } - if (s < 0) { + if (not_valid_socket(s)) { g_error("Ephemeral slirp_socket() allocation failed"); goto unix2inet6_cont; } diff --git a/src/socket.h b/src/socket.h index 27d3b8a..c7c6834 100644 --- a/src/socket.h +++ b/src/socket.h @@ -39,9 +39,9 @@ union slirp_sockaddr { struct socket { struct socket *so_next, *so_prev; /* For a linked list of sockets */ - int s; /* The actual socket */ - int s_aux; /* An auxiliary socket for miscellaneous use. Currently used to - * reserve OS ports in UNIX-to-inet translation. */ + slirp_os_socket s; /* The actual socket */ + slirp_os_socket s_aux; /* An auxiliary socket for miscellaneous use. Currently used to + * reserve OS ports in UNIX-to-inet translation. */ struct gfwd_list *guestfwd; int pollfds_idx; /* GPollFD GArray index */ @@ -180,7 +180,8 @@ static inline void sockaddr_copy(struct sockaddr *dst, socklen_t dstlen, const s /* Find the socket corresponding to lhost & fhost, trying last as a guess */ struct socket *solookup(struct socket **last, struct socket *head, - struct sockaddr_storage *lhost, struct sockaddr_storage *fhost); + const struct sockaddr_storage *lhost, + const struct sockaddr_storage *fhost); /* Create a new socket */ struct socket *socreate(Slirp *, int); /* Release a socket */ diff --git a/src/tcp_subr.c b/src/tcp_subr.c index 3cfe286..229b080 100644 --- a/src/tcp_subr.c +++ b/src/tcp_subr.c @@ -381,28 +381,30 @@ int tcp_fconnect(struct socket *so, unsigned short af) DEBUG_CALL("tcp_fconnect"); DEBUG_ARG("so = %p", so); - ret = so->s = slirp_socket(af, SOCK_STREAM, 0); - if (ret >= 0) { + so->s = slirp_socket(af, SOCK_STREAM, 0); + ret = have_valid_socket(so->s) ? 0 : -1; + if (ret) { ret = slirp_bind_outbound(so, af); if (ret < 0) { // bind failed - close socket closesocket(so->s); - so->s = -1; + so->s = SLIRP_INVALID_SOCKET; return (ret); } } if (ret >= 0) { - int opt, s = so->s; + int opt; + slirp_os_socket s = so->s; struct sockaddr_storage addr; slirp_set_nonblock(s); so->slirp->cb->register_poll_fd(s, so->slirp->opaque); slirp_socket_set_fast_reuse(s); opt = 1; - setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(opt)); + setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (const void *) &opt, sizeof(opt)); opt = 1; - setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)); + setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (const void *) &opt, sizeof(opt)); addr = so->fhost.ss; DEBUG_CALL(" connect()ing"); @@ -440,7 +442,8 @@ void tcp_connect(struct socket *inso) struct sockaddr_storage addr; socklen_t addrlen; struct tcpcb *tp; - int s, opt, ret; + slirp_os_socket s; + int opt, ret; /* AF_INET6 addresses are bigger than AF_INET, so this is big enough. */ char addrstr[INET6_ADDRSTRLEN]; char portstr[6]; @@ -480,8 +483,8 @@ void tcp_connect(struct socket *inso) DEBUG_MISC(" guest address not available yet"); addrlen = sizeof(addr); s = accept(inso->s, (struct sockaddr *)&addr, &addrlen); - if (s >= 0) { - close(s); + if (have_valid_socket(s)) { + closesocket(s); } return; } @@ -505,7 +508,7 @@ void tcp_connect(struct socket *inso) addrlen = sizeof(addr); s = accept(inso->s, (struct sockaddr *)&addr, &addrlen); - if (s < 0) { + if (not_valid_socket(s)) { tcp_close(sototcpcb(so)); /* This will sofree() as well */ return; } @@ -513,7 +516,7 @@ void tcp_connect(struct socket *inso) so->slirp->cb->register_poll_fd(s, so->slirp->opaque); slirp_socket_set_fast_reuse(s); opt = 1; - setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); + setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (const void *) &opt, sizeof(int)); slirp_socket_set_nodelay(s); so->fhost.ss = addr; @@ -967,7 +970,7 @@ int tcp_ctl(struct socket *so) if (ex_ptr->ex_fport == so->so_fport && so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) { if (ex_ptr->write_cb) { - so->s = -1; + so->s = SLIRP_INVALID_SOCKET; so->guestfwd = ex_ptr; return 1; } @@ -29,6 +29,11 @@ #include <sys/stat.h> #include <fcntl.h> +#if defined(_WIN32) +#include <io.h> +#include <share.h> +#endif + static inline int tftp_session_in_use(struct tftp_session *spt) { return (spt->slirp != NULL); @@ -297,13 +302,13 @@ static void tftp_handle_rrq(Slirp *slirp, struct sockaddr_storage *srcsas, /* check if a session already exists and if so terminate it */ s = tftp_session_find(slirp, srcsas, &tp->hdr); - if (s >= 0) { + if (have_valid_socket(s)) { tftp_session_terminate(&slirp->tftp_sessions[s]); } s = tftp_session_allocate(slirp, srcsas, &tp->hdr); - if (s < 0) { + if (not_valid_socket(s)) { return; } @@ -437,7 +442,7 @@ static void tftp_handle_ack(Slirp *slirp, struct sockaddr_storage *srcsas, s = tftp_session_find(slirp, srcsas, hdr); - if (s < 0) { + if (not_valid_socket(s)) { return; } @@ -451,7 +456,7 @@ static void tftp_handle_error(Slirp *slirp, struct sockaddr_storage *srcsas, s = tftp_session_find(slirp, srcsas, hdr); - if (s < 0) { + if (not_valid_socket(s)) { return; } @@ -178,7 +178,7 @@ void udp_input(register struct mbuf *m, int iphlen) * create one */ so = socreate(slirp, IPPROTO_UDP); - if (udp_attach(so, AF_INET) == -1) { + if (not_valid_socket(udp_attach(so, AF_INET))) { DEBUG_MISC(" udp_attach errno = %d-%s", errno, strerror(errno)); sofree(so); goto bad; @@ -220,7 +220,7 @@ void udp_input(register struct mbuf *m, int iphlen) icmp_send_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, 0, NULL); goto bad; } - setsockopt(so->s, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)); + setsockopt(so->s, IPPROTO_IP, IP_TTL, (const void *) &ttl, sizeof(ttl)); /* * Now we sendto() the packet. @@ -247,8 +247,8 @@ bad: m_free(m); } -int udp_output(struct socket *so, struct mbuf *m, struct sockaddr_in *saddr, - struct sockaddr_in *daddr, int iptos) +int udp_output(struct socket *so, struct mbuf *m, const struct sockaddr_in *saddr, + const struct sockaddr_in *daddr, int iptos) { Slirp *slirp = m->slirp; char addr[INET_ADDRSTRLEN]; @@ -303,15 +303,15 @@ int udp_output(struct socket *so, struct mbuf *m, struct sockaddr_in *saddr, return (error); } -int udp_attach(struct socket *so, unsigned short af) +slirp_os_socket udp_attach(struct socket *so, unsigned short af) { so->s = slirp_socket(af, SOCK_DGRAM, 0); - if (so->s != -1) { + if (have_valid_socket(so->s)) { if (slirp_bind_outbound(so, af) != 0) { // bind failed - close socket closesocket(so->s); - so->s = -1; - return -1; + so->s = SLIRP_INVALID_SOCKET; + return SLIRP_INVALID_SOCKET; } #ifdef __linux__ @@ -375,7 +375,7 @@ struct socket *udpx_listen(Slirp *slirp, so = socreate(slirp, IPPROTO_UDP); so->s = slirp_socket(haddr->sa_family, SOCK_DGRAM, 0); - if (so->s < 0) { + if (not_valid_socket(so->s)) { save_errno = errno; sofree(so); errno = save_errno; @@ -82,7 +82,7 @@ void udp_cleanup(Slirp *); /* Process UDP datagram coming from the guest */ void udp_input(register struct mbuf *, int); /* Create a host UDP socket, bound to this socket */ -int udp_attach(struct socket *, unsigned short af); +slirp_os_socket udp_attach(struct socket *, unsigned short af); /* Destroy socket */ void udp_detach(struct socket *); @@ -94,13 +94,13 @@ struct socket *udpx_listen(Slirp *, const struct sockaddr *laddr, socklen_t laddrlen, int flags); /* Send UDP datagram to the guest */ -int udp_output(struct socket *so, struct mbuf *m, struct sockaddr_in *saddr, - struct sockaddr_in *daddr, int iptos); +int udp_output(struct socket *so, struct mbuf *m, const struct sockaddr_in *saddr, + const struct sockaddr_in *daddr, int iptos); /* Process UDPv6 datagram coming from the guest */ void udp6_input(register struct mbuf *); /* Send UDPv6 datagram to the guest */ -int udp6_output(struct socket *so, struct mbuf *m, struct sockaddr_in6 *saddr, - struct sockaddr_in6 *daddr); +int udp6_output(struct socket *so, struct mbuf *m, const struct sockaddr_in6 *saddr, + const struct sockaddr_in6 *daddr); #endif @@ -96,7 +96,7 @@ void udp6_input(struct mbuf *m) if (so == NULL) { /* If there's no socket for this packet, create one. */ so = socreate(slirp, IPPROTO_UDP); - if (udp_attach(so, AF_INET6) == -1) { + if (not_valid_socket(udp_attach(so, AF_INET6))) { DEBUG_MISC(" udp6_attach errno = %d-%s", errno, strerror(errno)); sofree(so); goto bad; @@ -128,7 +128,7 @@ void udp6_input(struct mbuf *m) icmp6_send_error(m, ICMP6_TIMXCEED, ICMP6_TIMXCEED_INTRANS); goto bad; } - setsockopt(so->s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hop_limit, sizeof(hop_limit)); + setsockopt(so->s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, (const void *) &hop_limit, sizeof(hop_limit)); /* * Now we sendto() the packet. @@ -155,8 +155,8 @@ bad: m_free(m); } -int udp6_output(struct socket *so, struct mbuf *m, struct sockaddr_in6 *saddr, - struct sockaddr_in6 *daddr) +int udp6_output(struct socket *so, struct mbuf *m, const struct sockaddr_in6 *saddr, + const struct sockaddr_in6 *daddr) { Slirp *slirp = m->slirp; M_DUP_DEBUG(slirp, m, 0, sizeof(struct ip6) + sizeof(struct udphdr)); @@ -26,11 +26,15 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "util.h" - #include <glib.h> #include <fcntl.h> #include <stdint.h> +/* Windows: If errno.h is not included, then errno is a preprocessor define + * for WSAGetLastError(). errno.h redefines errno as a thread safe function, + * i.e. "*errno()", which allows us to assign errno a value. */ +#include <errno.h> + +#include "util.h" #if defined(_WIN32) int slirp_inet_aton(const char *cp, struct in_addr *ia) @@ -44,9 +48,10 @@ int slirp_inet_aton(const char *cp, struct in_addr *ia) } #endif -void slirp_set_nonblock(int fd) + +void slirp_set_nonblock(slirp_os_socket fd) { -#ifndef _WIN32 +#if !defined(_WIN32) int f; f = fcntl(fd, F_GETFL); assert(f != -1); @@ -58,14 +63,18 @@ void slirp_set_nonblock(int fd) #endif } -static void slirp_set_cloexec(int fd) +static void slirp_set_cloexec(slirp_os_socket fd) { -#ifndef _WIN32 +#if !defined(_WIN32) int f; f = fcntl(fd, F_GETFD); assert(f != -1); f = fcntl(fd, F_SETFD, f | FD_CLOEXEC); assert(f != -1); +#else +#ifdef GLIB_UNUSED_PARAM + GLIB_UNUSED_PARAM(fd); +#endif #endif } @@ -73,9 +82,9 @@ static void slirp_set_cloexec(int fd) * Opens a socket with FD_CLOEXEC set * On failure errno contains the reason. */ -int slirp_socket(int domain, int type, int protocol) +slirp_os_socket slirp_socket(int domain, int type, int protocol) { - int ret; + slirp_os_socket ret; #ifdef SOCK_CLOEXEC ret = socket(domain, type | SOCK_CLOEXEC, protocol); @@ -84,15 +93,15 @@ int slirp_socket(int domain, int type, int protocol) } #endif ret = socket(domain, type, protocol); - if (ret >= 0) { + if (have_valid_socket(ret)) { slirp_set_cloexec(ret); } return ret; } -#ifdef _WIN32 -static int socket_error(void) +#if defined(_WIN32) +static int win32_socket_error(void) { switch (WSAGetLastError()) { case 0: @@ -169,181 +178,182 @@ static int socket_error(void) } #undef ioctlsocket -int slirp_ioctlsocket_wrap(int fd, int req, void *val) +int slirp_ioctlsocket_wrap(slirp_os_socket fd, int req, void *val) { int ret; ret = ioctlsocket(fd, req, val); if (ret < 0) { - errno = socket_error(); + errno = win32_socket_error(); } return ret; } #undef closesocket -int slirp_closesocket_wrap(int fd) +int slirp_closesocket_wrap(slirp_os_socket fd) { int ret; ret = closesocket(fd); if (ret < 0) { - errno = socket_error(); + errno = win32_socket_error(); } return ret; } #undef connect -int slirp_connect_wrap(int sockfd, const struct sockaddr *addr, int addrlen) +int slirp_connect_wrap(slirp_os_socket sockfd, const struct sockaddr *addr, int addrlen) { int ret; ret = connect(sockfd, addr, addrlen); if (ret < 0) { - errno = socket_error(); + errno = win32_socket_error(); } return ret; } #undef listen -int slirp_listen_wrap(int sockfd, int backlog) +int slirp_listen_wrap(slirp_os_socket sockfd, int backlog) { int ret; ret = listen(sockfd, backlog); if (ret < 0) { - errno = socket_error(); + errno = win32_socket_error(); } return ret; } #undef bind -int slirp_bind_wrap(int sockfd, const struct sockaddr *addr, int addrlen) +int slirp_bind_wrap(slirp_os_socket sockfd, const struct sockaddr *addr, int addrlen) { int ret; ret = bind(sockfd, addr, addrlen); if (ret < 0) { - errno = socket_error(); + errno = win32_socket_error(); } return ret; } #undef socket -int slirp_socket_wrap(int domain, int type, int protocol) +slirp_os_socket slirp_socket_wrap(int domain, int type, int protocol) { - int ret; + slirp_os_socket ret; ret = socket(domain, type, protocol); if (ret < 0) { - errno = socket_error(); + errno = win32_socket_error(); } return ret; } #undef accept -int slirp_accept_wrap(int sockfd, struct sockaddr *addr, int *addrlen) +slirp_os_socket slirp_accept_wrap(slirp_os_socket sockfd, struct sockaddr *addr, int *addrlen) { - int ret; + slirp_os_socket ret; ret = accept(sockfd, addr, addrlen); if (ret < 0) { - errno = socket_error(); + errno = win32_socket_error(); } return ret; } #undef shutdown -int slirp_shutdown_wrap(int sockfd, int how) +int slirp_shutdown_wrap(slirp_os_socket sockfd, int how) { int ret; ret = shutdown(sockfd, how); if (ret < 0) { - errno = socket_error(); + errno = win32_socket_error(); } return ret; } #undef getsockopt -int slirp_getsockopt_wrap(int sockfd, int level, int optname, void *optval, +int slirp_getsockopt_wrap(slirp_os_socket sockfd, int level, int optname, void *optval, int *optlen) { int ret; ret = getsockopt(sockfd, level, optname, optval, optlen); if (ret < 0) { - errno = socket_error(); + errno = win32_socket_error(); } return ret; } #undef setsockopt -int slirp_setsockopt_wrap(int sockfd, int level, int optname, +int slirp_setsockopt_wrap(slirp_os_socket sockfd, int level, int optname, const void *optval, int optlen) { int ret; ret = setsockopt(sockfd, level, optname, optval, optlen); if (ret < 0) { - errno = socket_error(); + errno = win32_socket_error(); } return ret; } #undef getpeername -int slirp_getpeername_wrap(int sockfd, struct sockaddr *addr, int *addrlen) +int slirp_getpeername_wrap(slirp_os_socket sockfd, struct sockaddr *addr, int *addrlen) { int ret; ret = getpeername(sockfd, addr, addrlen); if (ret < 0) { - errno = socket_error(); + errno = win32_socket_error(); } return ret; } #undef getsockname -int slirp_getsockname_wrap(int sockfd, struct sockaddr *addr, int *addrlen) +int slirp_getsockname_wrap(slirp_os_socket sockfd, struct sockaddr *addr, int *addrlen) { int ret; ret = getsockname(sockfd, addr, addrlen); if (ret < 0) { - errno = socket_error(); + errno = win32_socket_error(); } return ret; } #undef send -slirp_ssize_t slirp_send_wrap(int sockfd, const void *buf, size_t len, int flags) +slirp_ssize_t slirp_send_wrap(slirp_os_socket sockfd, const void *buf, size_t len, int flags) { int ret; + ret = send(sockfd, buf, len, flags); if (ret < 0) { - errno = socket_error(); + errno = win32_socket_error(); } return ret; } #undef sendto -slirp_ssize_t slirp_sendto_wrap(int sockfd, const void *buf, size_t len, int flags, - const struct sockaddr *addr, int addrlen) +slirp_ssize_t slirp_sendto_wrap(slirp_os_socket sockfd, const void *buf, size_t len, int flags, + const struct sockaddr *addr, int addrlen) { int ret; ret = sendto(sockfd, buf, len, flags, addr, addrlen); if (ret < 0) { - errno = socket_error(); + errno = win32_socket_error(); } return ret; } #undef recv -slirp_ssize_t slirp_recv_wrap(int sockfd, void *buf, size_t len, int flags) +slirp_ssize_t slirp_recv_wrap(slirp_os_socket sockfd, void *buf, size_t len, int flags) { int ret; ret = recv(sockfd, buf, len, flags); if (ret < 0) { - errno = socket_error(); + errno = win32_socket_error(); } return ret; } #undef recvfrom -slirp_ssize_t slirp_recvfrom_wrap(int sockfd, void *buf, size_t len, int flags, - struct sockaddr *addr, int *addrlen) +slirp_ssize_t slirp_recvfrom_wrap(slirp_os_socket sockfd, void *buf, size_t len, int flags, + struct sockaddr *addr, int *addrlen) { int ret; ret = recvfrom(sockfd, buf, len, flags, addr, addrlen); if (ret < 0) { - errno = socket_error(); + errno = win32_socket_error(); } return ret; } @@ -361,7 +371,7 @@ void slirp_pstrcpy(char *buf, int buf_size, const char *str) c = *str++; if (c == 0 || q >= buf + buf_size - 1) break; - *q++ = c; + *q++ = (char) c; } *q = '\0'; } @@ -43,6 +43,7 @@ #include <sys/socket.h> #include <netinet/tcp.h> #include <netinet/in.h> +#include <sys/ioctl.h> #endif #include "libslirp.h" @@ -100,8 +101,18 @@ struct iovec { #define ETH_P_NCSI (0x88f8) #define ETH_P_UNKNOWN (0xffff) -/* FIXME: remove me when made standalone */ -#ifdef _WIN32 + +/* Windows: BLUF -- these functions have to have wrappers because Windows, just to + * be Windows, has error constants that are not the same as <errno.h>. Consequently, + * if one of the functions returns an error, the winsock2 error from WSAGetLastError() + * needs to be translated. + * + * To make the problem more complex, we have to ensure to include <errno.h>, which + * defines errno in a thread safe way. If we do not include <errno.h>, errno gets + * defined as WSAGetLastError(), which makes assigning a translated value impossible. + * Or ends up making the errno checking much more interesting than it has to be. + */ +#if defined(_WIN32) #undef accept #undef bind #undef closesocket @@ -118,72 +129,73 @@ struct iovec { #undef setsockopt #undef shutdown #undef socket -#endif -#ifdef _WIN32 #define connect slirp_connect_wrap -int slirp_connect_wrap(int fd, const struct sockaddr *addr, int addrlen); +int slirp_connect_wrap(slirp_os_socket fd, const struct sockaddr *addr, int addrlen); #define listen slirp_listen_wrap -int slirp_listen_wrap(int fd, int backlog); +int slirp_listen_wrap(slirp_os_socket fd, int backlog); #define bind slirp_bind_wrap -int slirp_bind_wrap(int fd, const struct sockaddr *addr, int addrlen); +int slirp_bind_wrap(slirp_os_socket fd, const struct sockaddr *addr, int addrlen); #define socket slirp_socket_wrap -int slirp_socket_wrap(int domain, int type, int protocol); +slirp_os_socket slirp_socket_wrap(int domain, int type, int protocol); #define accept slirp_accept_wrap -int slirp_accept_wrap(int fd, struct sockaddr *addr, int *addrlen); +slirp_os_socket slirp_accept_wrap(slirp_os_socket fd, struct sockaddr *addr, int *addrlen); #define shutdown slirp_shutdown_wrap -int slirp_shutdown_wrap(int fd, int how); +int slirp_shutdown_wrap(slirp_os_socket fd, int how); #define getpeername slirp_getpeername_wrap -int slirp_getpeername_wrap(int fd, struct sockaddr *addr, int *addrlen); +int slirp_getpeername_wrap(slirp_os_socket fd, struct sockaddr *addr, int *addrlen); #define getsockname slirp_getsockname_wrap -int slirp_getsockname_wrap(int fd, struct sockaddr *addr, int *addrlen); +int slirp_getsockname_wrap(slirp_os_socket fd, struct sockaddr *addr, int *addrlen); #define send slirp_send_wrap -slirp_ssize_t slirp_send_wrap(int fd, const void *buf, size_t len, int flags); +slirp_ssize_t slirp_send_wrap(slirp_os_socket fd, const void *buf, size_t len, int flags); #define sendto slirp_sendto_wrap -slirp_ssize_t slirp_sendto_wrap(int fd, const void *buf, size_t len, int flags, +slirp_ssize_t slirp_sendto_wrap(slirp_os_socket fd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, int addrlen); #define recv slirp_recv_wrap -slirp_ssize_t slirp_recv_wrap(int fd, void *buf, size_t len, int flags); +slirp_ssize_t slirp_recv_wrap(slirp_os_socket fd, void *buf, size_t len, int flags); #define recvfrom slirp_recvfrom_wrap -slirp_ssize_t slirp_recvfrom_wrap(int fd, void *buf, size_t len, int flags, +slirp_ssize_t slirp_recvfrom_wrap(slirp_os_socket fd, void *buf, size_t len, int flags, struct sockaddr *src_addr, int *addrlen); #define closesocket slirp_closesocket_wrap -int slirp_closesocket_wrap(int fd); +int slirp_closesocket_wrap(slirp_os_socket fd); #define ioctlsocket slirp_ioctlsocket_wrap -int slirp_ioctlsocket_wrap(int fd, int req, void *val); +int slirp_ioctlsocket_wrap(slirp_os_socket fd, int req, void *val); #define getsockopt slirp_getsockopt_wrap -int slirp_getsockopt_wrap(int sockfd, int level, int optname, void *optval, +int slirp_getsockopt_wrap(slirp_os_socket sockfd, int level, int optname, void *optval, int *optlen); #define setsockopt slirp_setsockopt_wrap -int slirp_setsockopt_wrap(int sockfd, int level, int optname, +int slirp_setsockopt_wrap(slirp_os_socket sockfd, int level, int optname, const void *optval, int optlen); #define inet_aton slirp_inet_aton -int slirp_inet_aton(const char *cp, struct in_addr *ia); #else #define closesocket(s) close(s) #define ioctlsocket(s, r, v) ioctl(s, r, v) #endif -int slirp_socket(int domain, int type, int protocol); -void slirp_set_nonblock(int fd); +slirp_os_socket slirp_socket(int domain, int type, int protocol); +void slirp_set_nonblock(slirp_os_socket fd); -static inline int slirp_socket_set_v6only(int fd, int v) +static inline int slirp_socket_set_v6only(slirp_os_socket fd, int v) { - return setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &v, sizeof(v)); + return setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const void *) &v, sizeof(v)); } -static inline int slirp_socket_set_nodelay(int fd) +static inline int slirp_socket_set_nodelay(slirp_os_socket fd) { int v = 1; - return setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v)); + return setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const void *) &v, sizeof(v)); } -static inline int slirp_socket_set_fast_reuse(int fd) +static inline int slirp_socket_set_fast_reuse(slirp_os_socket fd) { #ifndef _WIN32 int v = 1; return setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &v, sizeof(v)); #else +#ifdef GLIB_UNUSED_PARAM + GLIB_UNUSED_PARAM(fd); +#endif + /* Enabling the reuse of an endpoint that was used by a socket still in * TIME_WAIT state is usually performed by setting SO_REUSEADDR. On Windows * fast reuse is the default and SO_REUSEADDR does strange things. So we @@ -193,6 +205,22 @@ static inline int slirp_socket_set_fast_reuse(int fd) #endif } +/* Socket error check */ +static inline int have_valid_socket(slirp_os_socket s) +{ +#if !defined(_WIN32) + return (s >= 0); +#else + return (s != SLIRP_INVALID_SOCKET); +#endif +} + +/* And the inverse -- the code reads more smoothly vs "!have_valid_socket" */ +static inline int not_valid_socket(slirp_os_socket s) +{ + return !have_valid_socket(s); +} + void slirp_pstrcpy(char *buf, int buf_size, const char *str); int slirp_fmt(char *str, size_t size, const char *format, ...) G_GNUC_PRINTF(3, 4); |