提交 707bd47e 编写于 作者: M Marc-André Lureau 提交者: Samuel Thibault

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: NMarc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: NSamuel Thibault <samuel.thibault@ens-lyon.org>
上级 90329416
......@@ -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
......
......@@ -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;
......
/*
* 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 */
......@@ -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
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册