From nobody Mon Sep 29 02:41:45 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1547726157349591.3471215478772; Thu, 17 Jan 2019 03:55:57 -0800 (PST) Received: from localhost ([127.0.0.1]:42736 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gk6H6-00057O-75 for importer@patchew.org; Thu, 17 Jan 2019 06:55:56 -0500 Received: from eggs.gnu.org ([209.51.188.92]:57247) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gk66M-0005YE-DL for qemu-devel@nongnu.org; Thu, 17 Jan 2019 06:44:52 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gk66K-0004cW-Bm for qemu-devel@nongnu.org; Thu, 17 Jan 2019 06:44:50 -0500 Received: from mx1.redhat.com ([209.132.183.28]:49156) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gk66J-0004Z6-H4 for qemu-devel@nongnu.org; Thu, 17 Jan 2019 06:44:48 -0500 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 32479C0528AA; Thu, 17 Jan 2019 11:44:46 +0000 (UTC) Received: from localhost (unknown [10.36.112.10]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2452819751; Thu, 17 Jan 2019 11:44:43 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Thu, 17 Jan 2019 15:43:40 +0400 Message-Id: <20190117114359.5164-9-marcandre.lureau@redhat.com> In-Reply-To: <20190117114359.5164-1-marcandre.lureau@redhat.com> References: <20190117114359.5164-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Thu, 17 Jan 2019 11:44:46 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH 08/27] slirp: replace most qemu socket utilities with slirp own version X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Li Zhijian , Jan Kiszka , Jason Wang , Zhang Chen , Samuel Thibault , pbonzini@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" qemu_set_nonblock() is slightly more problematic and will be dealt with in a separate patch. Signed-off-by: Marc-Andr=C3=A9 Lureau --- slirp/util.h | 59 +++++++++++++++ slirp/ip_icmp.c | 6 +- slirp/misc.c | 20 ++--- slirp/socket.c | 18 ++--- slirp/tcp_subr.c | 18 ++--- slirp/udp.c | 8 +- slirp/util.c | 176 ++++++++++++++++++++++++++++++++++++++++++++ slirp/Makefile.objs | 1 + 8 files changed, 271 insertions(+), 35 deletions(-) create mode 100644 slirp/util.c diff --git a/slirp/util.h b/slirp/util.h index 00291c30a67..050ca7f1a3f 100644 --- a/slirp/util.h +++ b/slirp/util.h @@ -23,10 +23,69 @@ #ifndef UTIL_H_ #define UTIL_H_ =20 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#else +#include +#include +#include +#endif + #if defined(_WIN32) # define SLIRP_PACKED __attribute__((gcc_struct, packed)) #else # define SLIRP_PACKED __attribute__((packed)) #endif =20 +#ifdef _WIN32 +int slirp_closesocket(int fd); +int slirp_ioctlsocket(int fd, int req, void *val); +int inet_aton(const char *cp, struct in_addr *ia); +#define slirp_getsockopt(sockfd, level, optname, optval, optlen) \ + getsockopt(sockfd, level, optname, (void *)optval, optlen) +#define slirp_setsockopt(sockfd, level, optname, optval, optlen) \ + setsockopt(sockfd, level, optname, (const void *)optval, optlen) +#define slirp_recv(sockfd, buf, len, flags) recv(sockfd, (void *)buf, len,= flags) +#else +#define slirp_setsockopt setsockopt +#define slirp_getsockopt getsockopt +#define slirp_recv recv +#define slirp_closesocket close +#define slirp_ioctlsocket ioctl +#endif + +int slirp_socket(int domain, int type, int protocol); + +static inline int slirp_socket_set_nodelay(int fd) +{ + int v =3D 1; + return slirp_setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v)); +} + +static inline int slirp_socket_set_fast_reuse(int fd) +{ +#ifndef _WIN32 + int v =3D 1; + return slirp_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &v, sizeof(v)); +#else + /* 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 Wi= ndows + * fast reuse is the default and SO_REUSEADDR does strange things. So = we + * don't have to do anything here. More info can be found at: + * http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621.as= px */ + return 0; +#endif +} + #endif diff --git a/slirp/ip_icmp.c b/slirp/ip_icmp.c index 7c7e042049d..b59daa801d1 100644 --- a/slirp/ip_icmp.c +++ b/slirp/ip_icmp.c @@ -83,7 +83,7 @@ static int icmp_send(struct socket *so, struct mbuf *m, i= nt hlen) struct ip *ip =3D mtod(m, struct ip *); struct sockaddr_in addr; =20 - so->s =3D qemu_socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP); + so->s =3D slirp_socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP); if (so->s =3D=3D -1) { return -1; } @@ -114,7 +114,7 @@ static int icmp_send(struct socket *so, struct mbuf *m,= int hlen) =20 void icmp_detach(struct socket *so) { - closesocket(so->s); + slirp_closesocket(so->s); sofree(so); } =20 @@ -421,7 +421,7 @@ void icmp_receive(struct socket *so) icp =3D mtod(m, struct icmp *); =20 id =3D icp->icmp_id; - len =3D qemu_recv(so->s, icp, M_ROOM(m), 0); + len =3D slirp_recv(so->s, icp, M_ROOM(m), 0); /* * The behavior of reading SOCK_DGRAM+IPPROTO_ICMP sockets is inconsis= tent * between host OSes. On Linux, only the ICMP header and payload is diff --git a/slirp/misc.c b/slirp/misc.c index b8a2bf971af..32ec02a5251 100644 --- a/slirp/misc.c +++ b/slirp/misc.c @@ -72,14 +72,14 @@ slirp_socketpair_with_oob(int sv[2]) int ret, s; =20 sv[1] =3D -1; - s =3D qemu_socket(AF_INET, SOCK_STREAM, 0); + s =3D slirp_socket(AF_INET, SOCK_STREAM, 0); if (s < 0 || bind(s, (struct sockaddr *)&addr, addrlen) < 0 || listen(s, 1) < 0 || getsockname(s, (struct sockaddr *)&addr, &addrlen) < 0) { goto err; } =20 - sv[1] =3D qemu_socket(AF_INET, SOCK_STREAM, 0); + sv[1] =3D slirp_socket(AF_INET, SOCK_STREAM, 0); if (sv[1] < 0) { goto err; } @@ -102,16 +102,16 @@ slirp_socketpair_with_oob(int sv[2]) goto err; } =20 - closesocket(s); + slirp_closesocket(s); return 0; =20 err: g_critical("slirp_socketpair(): %s", strerror(errno)); if (s >=3D 0) { - closesocket(s); + slirp_closesocket(s); } if (sv[1] >=3D 0) { - closesocket(sv[1]); + slirp_closesocket(sv[1]); } return -1; } @@ -153,16 +153,16 @@ fork_exec(struct socket *so, const char *ex) if (err) { g_critical("fork_exec: %s", err->message); g_error_free(err); - closesocket(sp[0]); - closesocket(sp[1]); + slirp_closesocket(sp[0]); + slirp_closesocket(sp[1]); return 0; } =20 so->s =3D sp[0]; - closesocket(sp[1]); - socket_set_fast_reuse(so->s); + slirp_closesocket(sp[1]); + slirp_socket_set_fast_reuse(so->s); opt =3D 1; - qemu_setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); + slirp_setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); qemu_set_nonblock(so->s); return 1; } diff --git a/slirp/socket.c b/slirp/socket.c index 5ffbaa064a5..5805d30f3d8 100644 --- a/slirp/socket.c +++ b/slirp/socket.c @@ -187,7 +187,7 @@ soread(struct socket *so) */ sopreprbuf(so, iov, &n); =20 - nn =3D qemu_recv(so->s, iov[0].iov_base, iov[0].iov_len,0); + nn =3D slirp_recv(so->s, iov[0].iov_base, iov[0].iov_len,0); if (nn <=3D 0) { if (nn < 0 && (errno =3D=3D EINTR || errno =3D=3D EAGAIN)) return 0; @@ -203,7 +203,7 @@ soread(struct socket *so) if (getpeername(so->s, paddr, &alen) < 0) { err =3D errno; } else { - getsockopt(so->s, SOL_SOCKET, SO_ERROR, + slirp_getsockopt(so->s, SOL_SOCKET, SO_ERROR, &err, &elen); } } @@ -233,7 +233,7 @@ soread(struct socket *so) */ if (n =3D=3D 2 && nn =3D=3D iov[0].iov_len) { int ret; - ret =3D qemu_recv(so->s, iov[1].iov_base, iov[1].iov_len,0); + ret =3D slirp_recv(so->s, iov[1].iov_base, iov[1].iov_len,0); if (ret > 0) nn +=3D ret; } @@ -554,7 +554,7 @@ sorecvfrom(struct socket *so) */ len =3D M_FREEROOM(m); /* if (so->so_fport !=3D htons(53)) { */ - ioctlsocket(so->s, FIONREAD, &n); + slirp_ioctlsocket(so->s, FIONREAD, &n); =20 if (n > len) { n =3D (m->m_data - m->m_dat) + m->m_len + n + 1; @@ -719,14 +719,14 @@ tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport,= uint32_t laddr, addr.sin_addr.s_addr =3D haddr; addr.sin_port =3D hport; =20 - if (((s =3D qemu_socket(AF_INET,SOCK_STREAM,0)) < 0) || - (socket_set_fast_reuse(s) < 0) || + if (((s =3D slirp_socket(AF_INET,SOCK_STREAM,0)) < 0) || + (slirp_socket_set_fast_reuse(s) < 0) || (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) || (listen(s,1) < 0)) { int tmperrno =3D errno; /* Don't clobber the real reason we failed */ =20 if (s >=3D 0) { - closesocket(s); + slirp_closesocket(s); } sofree(so); /* Restore the real errno */ @@ -737,9 +737,9 @@ tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, u= int32_t laddr, #endif return NULL; } - qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); + slirp_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); opt =3D 1; - qemu_setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(int)); + slirp_setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(int)); =20 getsockname(s,(struct sockaddr *)&addr,&addrlen); so->so_ffamily =3D AF_INET; diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c index 4e81736d6fd..3567f320ff0 100644 --- a/slirp/tcp_subr.c +++ b/slirp/tcp_subr.c @@ -337,7 +337,7 @@ tcp_close(struct tcpcb *tp) /* clobber input socket cache if we're closing the cached connection */ if (so =3D=3D slirp->tcp_last_so) slirp->tcp_last_so =3D &slirp->tcb; - closesocket(so->s); + slirp_closesocket(so->s); sbfree(&so->so_rcv); sbfree(&so->so_snd); sofree(so); @@ -407,17 +407,17 @@ int tcp_fconnect(struct socket *so, unsigned short af) DEBUG_CALL("tcp_fconnect"); DEBUG_ARG("so =3D %p", so); =20 - ret =3D so->s =3D qemu_socket(af, SOCK_STREAM, 0); + ret =3D so->s =3D slirp_socket(af, SOCK_STREAM, 0); if (ret >=3D 0) { int opt, s=3Dso->s; struct sockaddr_storage addr; =20 qemu_set_nonblock(s); - socket_set_fast_reuse(s); + slirp_socket_set_fast_reuse(s); opt =3D 1; - qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(opt)); + slirp_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(opt)); opt =3D 1; - qemu_setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)); + slirp_setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)); =20 addr =3D so->fhost.ss; DEBUG_CALL(" connect()ing"); @@ -485,10 +485,10 @@ void tcp_connect(struct socket *inso) return; } qemu_set_nonblock(s); - socket_set_fast_reuse(s); + slirp_socket_set_fast_reuse(s); opt =3D 1; - qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); - socket_set_nodelay(s); + slirp_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); + slirp_socket_set_nodelay(s); =20 so->fhost.ss =3D addr; sotranslate_accept(so); @@ -496,7 +496,7 @@ void tcp_connect(struct socket *inso) /* Close the accept() socket, set right state */ if (inso->so_state & SS_FACCEPTONCE) { /* If we only accept once, close the accept() socket */ - closesocket(so->s); + slirp_closesocket(so->s); =20 /* Don't select it yet, even though we have an FD */ /* if it's not FACCEPTONCE, it's already NOFDREF */ diff --git a/slirp/udp.c b/slirp/udp.c index 309feb9aaef..6c3fb9a29ff 100644 --- a/slirp/udp.c +++ b/slirp/udp.c @@ -281,7 +281,7 @@ int udp_output(struct socket *so, struct mbuf *m, int udp_attach(struct socket *so, unsigned short af) { - so->s =3D qemu_socket(af, SOCK_DGRAM, 0); + so->s =3D slirp_socket(af, SOCK_DGRAM, 0); if (so->s !=3D -1) { so->so_expire =3D curtime + SO_EXPIRE; insque(so, &so->slirp->udb); @@ -292,7 +292,7 @@ udp_attach(struct socket *so, unsigned short af) void udp_detach(struct socket *so) { - closesocket(so->s); + slirp_closesocket(so->s); sofree(so); } =20 @@ -327,7 +327,7 @@ udp_listen(Slirp *slirp, uint32_t haddr, u_int hport, u= int32_t laddr, socklen_t addrlen =3D sizeof(struct sockaddr_in); =20 so =3D socreate(slirp); - so->s =3D qemu_socket(AF_INET,SOCK_DGRAM,0); + so->s =3D slirp_socket(AF_INET,SOCK_DGRAM,0); if (so->s < 0) { sofree(so); return NULL; @@ -343,7 +343,7 @@ udp_listen(Slirp *slirp, uint32_t haddr, u_int hport, u= int32_t laddr, udp_detach(so); return NULL; } - socket_set_fast_reuse(so->s); + slirp_socket_set_fast_reuse(so->s); =20 getsockname(so->s,(struct sockaddr *)&addr,&addrlen); so->fhost.sin =3D addr; diff --git a/slirp/util.c b/slirp/util.c new file mode 100644 index 00000000000..b1a36b27bc5 --- /dev/null +++ b/slirp/util.c @@ -0,0 +1,176 @@ +/* + * util.c (mostly based on QEMU os-win32.c) + * + * Copyright (c) 2003-2008 Fabrice Bellard + * Copyright (c) 2010-2016 Red Hat, Inc. + * + * QEMU library functions for win32 which are shared between QEMU and + * the QEMU tools. + * + * Permission is hereby granted, free of charge, to any person obtaining a= copy + * of this software and associated documentation files (the "Software"), t= o deal + * in the Software without restriction, including without limitation the r= ights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included= in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS= OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OT= HER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING= FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS = IN + * THE SOFTWARE. + */ +#include "util.h" + +#include +#include +#include + +#if defined(_WIN32) && !defined(WITH_QEMU) +int inet_aton(const char *cp, struct in_addr *ia) +{ + uint32_t addr =3D inet_addr(cp); + if (addr =3D=3D 0xffffffff) { + return 0; + } + ia->s_addr =3D addr; + return 1; +} +#endif + +static void slirp_set_cloexec(int fd) +{ +#ifndef _WIN32 + int f; + f =3D fcntl(fd, F_GETFD); + assert(f !=3D -1); + f =3D fcntl(fd, F_SETFD, f | FD_CLOEXEC); + assert(f !=3D -1); +#endif +} + +/* + * Opens a socket with FD_CLOEXEC set + */ +int slirp_socket(int domain, int type, int protocol) +{ + int ret; + +#ifdef SOCK_CLOEXEC + ret =3D socket(domain, type | SOCK_CLOEXEC, protocol); + if (ret !=3D -1 || errno !=3D EINVAL) { + return ret; + } +#endif + ret =3D socket(domain, type, protocol); + if (ret >=3D 0) { + slirp_set_cloexec(ret); + } + + return ret; +} + +#ifdef _WIN32 +static int socket_error(void) +{ + switch (WSAGetLastError()) { + case 0: + return 0; + case WSAEINTR: + return EINTR; + case WSAEINVAL: + return EINVAL; + case WSA_INVALID_HANDLE: + return EBADF; + case WSA_NOT_ENOUGH_MEMORY: + return ENOMEM; + case WSA_INVALID_PARAMETER: + return EINVAL; + case WSAENAMETOOLONG: + return ENAMETOOLONG; + case WSAENOTEMPTY: + return ENOTEMPTY; + case WSAEWOULDBLOCK: + /* not using EWOULDBLOCK as we don't want code to have + * to check both EWOULDBLOCK and EAGAIN */ + return EAGAIN; + case WSAEINPROGRESS: + return EINPROGRESS; + case WSAEALREADY: + return EALREADY; + case WSAENOTSOCK: + return ENOTSOCK; + case WSAEDESTADDRREQ: + return EDESTADDRREQ; + case WSAEMSGSIZE: + return EMSGSIZE; + case WSAEPROTOTYPE: + return EPROTOTYPE; + case WSAENOPROTOOPT: + return ENOPROTOOPT; + case WSAEPROTONOSUPPORT: + return EPROTONOSUPPORT; + case WSAEOPNOTSUPP: + return EOPNOTSUPP; + case WSAEAFNOSUPPORT: + return EAFNOSUPPORT; + case WSAEADDRINUSE: + return EADDRINUSE; + case WSAEADDRNOTAVAIL: + return EADDRNOTAVAIL; + case WSAENETDOWN: + return ENETDOWN; + case WSAENETUNREACH: + return ENETUNREACH; + case WSAENETRESET: + return ENETRESET; + case WSAECONNABORTED: + return ECONNABORTED; + case WSAECONNRESET: + return ECONNRESET; + case WSAENOBUFS: + return ENOBUFS; + case WSAEISCONN: + return EISCONN; + case WSAENOTCONN: + return ENOTCONN; + case WSAETIMEDOUT: + return ETIMEDOUT; + case WSAECONNREFUSED: + return ECONNREFUSED; + case WSAELOOP: + return ELOOP; + case WSAEHOSTUNREACH: + return EHOSTUNREACH; + default: + return EIO; + } +} + +#undef ioctlsocket +int slirp_ioctlsocket(int fd, int req, void *val) +{ + int ret; + ret =3D ioctlsocket(fd, req, val); + if (ret < 0) { + errno =3D socket_error(); + } + return ret; +} + +#undef closesocket +int slirp_closesocket(int fd) +{ + int ret; + ret =3D closesocket(fd); + if (ret < 0) { + errno =3D socket_error(); + } + return ret; +} +#endif /* WIN32 */ diff --git a/slirp/Makefile.objs b/slirp/Makefile.objs index 959558c7328..38ebdb416e3 100644 --- a/slirp/Makefile.objs +++ b/slirp/Makefile.objs @@ -27,6 +27,7 @@ slirp.mo-objs =3D \ tftp.o \ udp.o \ udp6.o \ + util.o \ $(NULL) =20 slirp.mo-cflags =3D -DG_LOG_DOMAIN=3D\"Slirp\" --=20 2.20.1.98.gecbdaf0899