slirp: replace most qemu socket utilities with slirp own version
qemu_set_nonblock() is slightly more problematic and will be dealt with in a separate patch. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
This commit is contained in:
parent
9032941640
commit
707bd47ef3
@ -27,6 +27,7 @@ slirp.mo-objs = \
|
||||
tftp.o \
|
||||
udp.o \
|
||||
udp6.o \
|
||||
util.o \
|
||||
$(NULL)
|
||||
|
||||
slirp.mo-cflags = -DG_LOG_DOMAIN=\"Slirp\"
|
||||
slirp.mo-cflags = -DG_LOG_DOMAIN=\"Slirp\" -DWITH_QEMU
|
||||
|
@ -83,7 +83,7 @@ static int icmp_send(struct socket *so, struct mbuf *m, int hlen)
|
||||
struct ip *ip = mtod(m, struct ip *);
|
||||
struct sockaddr_in addr;
|
||||
|
||||
so->s = qemu_socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
|
||||
so->s = slirp_socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
|
||||
if (so->s == -1) {
|
||||
return -1;
|
||||
}
|
||||
@ -114,7 +114,7 @@ static int icmp_send(struct socket *so, struct mbuf *m, int hlen)
|
||||
|
||||
void icmp_detach(struct socket *so)
|
||||
{
|
||||
closesocket(so->s);
|
||||
slirp_closesocket(so->s);
|
||||
sofree(so);
|
||||
}
|
||||
|
||||
@ -421,7 +421,7 @@ void icmp_receive(struct socket *so)
|
||||
icp = mtod(m, struct icmp *);
|
||||
|
||||
id = icp->icmp_id;
|
||||
len = qemu_recv(so->s, icp, M_ROOM(m), 0);
|
||||
len = slirp_recv(so->s, icp, M_ROOM(m), 0);
|
||||
/*
|
||||
* The behavior of reading SOCK_DGRAM+IPPROTO_ICMP sockets is inconsistent
|
||||
* between host OSes. On Linux, only the ICMP header and payload is
|
||||
|
20
slirp/misc.c
20
slirp/misc.c
@ -72,14 +72,14 @@ slirp_socketpair_with_oob(int sv[2])
|
||||
int ret, s;
|
||||
|
||||
sv[1] = -1;
|
||||
s = qemu_socket(AF_INET, SOCK_STREAM, 0);
|
||||
s = 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;
|
||||
}
|
||||
|
||||
sv[1] = qemu_socket(AF_INET, SOCK_STREAM, 0);
|
||||
sv[1] = 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;
|
||||
}
|
||||
|
||||
closesocket(s);
|
||||
slirp_closesocket(s);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
g_critical("slirp_socketpair(): %s", strerror(errno));
|
||||
if (s >= 0) {
|
||||
closesocket(s);
|
||||
slirp_closesocket(s);
|
||||
}
|
||||
if (sv[1] >= 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;
|
||||
}
|
||||
|
||||
so->s = sp[0];
|
||||
closesocket(sp[1]);
|
||||
socket_set_fast_reuse(so->s);
|
||||
slirp_closesocket(sp[1]);
|
||||
slirp_socket_set_fast_reuse(so->s);
|
||||
opt = 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;
|
||||
}
|
||||
|
@ -187,7 +187,7 @@ soread(struct socket *so)
|
||||
*/
|
||||
sopreprbuf(so, iov, &n);
|
||||
|
||||
nn = qemu_recv(so->s, iov[0].iov_base, iov[0].iov_len,0);
|
||||
nn = slirp_recv(so->s, iov[0].iov_base, iov[0].iov_len,0);
|
||||
if (nn <= 0) {
|
||||
if (nn < 0 && (errno == EINTR || errno == EAGAIN))
|
||||
return 0;
|
||||
@ -203,7 +203,7 @@ soread(struct socket *so)
|
||||
if (getpeername(so->s, paddr, &alen) < 0) {
|
||||
err = 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 == 2 && nn == iov[0].iov_len) {
|
||||
int ret;
|
||||
ret = qemu_recv(so->s, iov[1].iov_base, iov[1].iov_len,0);
|
||||
ret = slirp_recv(so->s, iov[1].iov_base, iov[1].iov_len,0);
|
||||
if (ret > 0)
|
||||
nn += ret;
|
||||
}
|
||||
@ -554,7 +554,7 @@ sorecvfrom(struct socket *so)
|
||||
*/
|
||||
len = M_FREEROOM(m);
|
||||
/* if (so->so_fport != htons(53)) { */
|
||||
ioctlsocket(so->s, FIONREAD, &n);
|
||||
slirp_ioctlsocket(so->s, FIONREAD, &n);
|
||||
|
||||
if (n > len) {
|
||||
n = (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 = haddr;
|
||||
addr.sin_port = hport;
|
||||
|
||||
if (((s = qemu_socket(AF_INET,SOCK_STREAM,0)) < 0) ||
|
||||
(socket_set_fast_reuse(s) < 0) ||
|
||||
if (((s = 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 = errno; /* Don't clobber the real reason we failed */
|
||||
|
||||
if (s >= 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, uint32_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 = 1;
|
||||
qemu_setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(int));
|
||||
slirp_setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(int));
|
||||
|
||||
getsockname(s,(struct sockaddr *)&addr,&addrlen);
|
||||
so->so_ffamily = AF_INET;
|
||||
|
@ -337,7 +337,7 @@ tcp_close(struct tcpcb *tp)
|
||||
/* clobber input socket cache if we're closing the cached connection */
|
||||
if (so == slirp->tcp_last_so)
|
||||
slirp->tcp_last_so = &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 = %p", so);
|
||||
|
||||
ret = so->s = qemu_socket(af, SOCK_STREAM, 0);
|
||||
ret = so->s = slirp_socket(af, SOCK_STREAM, 0);
|
||||
if (ret >= 0) {
|
||||
int opt, s=so->s;
|
||||
struct sockaddr_storage addr;
|
||||
|
||||
qemu_set_nonblock(s);
|
||||
socket_set_fast_reuse(s);
|
||||
slirp_socket_set_fast_reuse(s);
|
||||
opt = 1;
|
||||
qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(opt));
|
||||
slirp_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(opt));
|
||||
opt = 1;
|
||||
qemu_setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
|
||||
slirp_setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
|
||||
|
||||
addr = 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 = 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);
|
||||
|
||||
so->fhost.ss = 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);
|
||||
|
||||
/* Don't select it yet, even though we have an FD */
|
||||
/* if it's not FACCEPTONCE, it's already NOFDREF */
|
||||
|
@ -281,7 +281,7 @@ int udp_output(struct socket *so, struct mbuf *m,
|
||||
int
|
||||
udp_attach(struct socket *so, unsigned short af)
|
||||
{
|
||||
so->s = qemu_socket(af, SOCK_DGRAM, 0);
|
||||
so->s = slirp_socket(af, SOCK_DGRAM, 0);
|
||||
if (so->s != -1) {
|
||||
so->so_expire = 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);
|
||||
}
|
||||
|
||||
@ -327,7 +327,7 @@ udp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
|
||||
socklen_t addrlen = sizeof(struct sockaddr_in);
|
||||
|
||||
so = socreate(slirp);
|
||||
so->s = qemu_socket(AF_INET,SOCK_DGRAM,0);
|
||||
so->s = 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, uint32_t laddr,
|
||||
udp_detach(so);
|
||||
return NULL;
|
||||
}
|
||||
socket_set_fast_reuse(so->s);
|
||||
slirp_socket_set_fast_reuse(so->s);
|
||||
|
||||
getsockname(so->s,(struct sockaddr *)&addr,&addrlen);
|
||||
so->fhost.sin = addr;
|
||||
|
176
slirp/util.c
Normal file
176
slirp/util.c
Normal file
@ -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"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* 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 OTHER
|
||||
* 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 <glib.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(_WIN32) && !defined(WITH_QEMU)
|
||||
int inet_aton(const char *cp, struct in_addr *ia)
|
||||
{
|
||||
uint32_t addr = inet_addr(cp);
|
||||
if (addr == 0xffffffff) {
|
||||
return 0;
|
||||
}
|
||||
ia->s_addr = addr;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void slirp_set_cloexec(int fd)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
int f;
|
||||
f = fcntl(fd, F_GETFD);
|
||||
assert(f != -1);
|
||||
f = fcntl(fd, F_SETFD, f | FD_CLOEXEC);
|
||||
assert(f != -1);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Opens a socket with FD_CLOEXEC set
|
||||
*/
|
||||
int slirp_socket(int domain, int type, int protocol)
|
||||
{
|
||||
int ret;
|
||||
|
||||
#ifdef SOCK_CLOEXEC
|
||||
ret = socket(domain, type | SOCK_CLOEXEC, protocol);
|
||||
if (ret != -1 || errno != EINVAL) {
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
ret = socket(domain, type, protocol);
|
||||
if (ret >= 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 = ioctlsocket(fd, req, val);
|
||||
if (ret < 0) {
|
||||
errno = socket_error();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef closesocket
|
||||
int slirp_closesocket(int fd)
|
||||
{
|
||||
int ret;
|
||||
ret = closesocket(fd);
|
||||
if (ret < 0) {
|
||||
errno = socket_error();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif /* WIN32 */
|
61
slirp/util.h
61
slirp/util.h
@ -23,10 +23,71 @@
|
||||
#ifndef UTIL_H_
|
||||
#define UTIL_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
# define SLIRP_PACKED __attribute__((gcc_struct, packed))
|
||||
#else
|
||||
# define SLIRP_PACKED __attribute__((packed))
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
int slirp_closesocket(int fd);
|
||||
int slirp_ioctlsocket(int fd, int req, void *val);
|
||||
#ifndef WITH_QEMU
|
||||
int inet_aton(const char *cp, struct in_addr *ia);
|
||||
#endif
|
||||
#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 = 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 = 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 Windows
|
||||
* 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.aspx */
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user