More work towards libslirp

Marc-André Lureau (27):
   slirp: generalize guestfwd with a callback based approach
   net/slirp: simplify checking for cmd: prefix
   net/slirp: free forwarding rules on cleanup
   net/slirp: fix leaks on forwarding rule registration error
   slirp: add callbacks for timer
   slirp: replace trace functions with DEBUG calls
   slirp: replace QEMU_PACKED with SLIRP_PACKED
   slirp: replace most qemu socket utilities with slirp own version
   slirp: replace qemu_set_nonblock()
   slirp: add unregister_poll_fd() callback
   slirp: replace qemu_notify_event() with a callback
   slirp: move QEMU state saving to a separate unit
   slirp: do not include qemu headers in libslirp.h public API header
   slirp: improve windows headers inclusion
   slirp: add slirp own version of pstrcpy
   slirp: remove qemu timer.h dependency
   slirp: remove now useless QEMU headers inclusions
   slirp: replace net/eth.h inclusion with own defines
   slirp: replace qemu qtailq with slirp own copy
   slirp: replace remaining qemu headers dependency
   slirp: prefer c99 types over BSD kind
   slirp: improve send_packet() callback
   slirp: replace global polling with per-instance & notifier
   slirp: remove slirp_instances list
   slirp: use polling callbacks, drop glib requirement
   slirp: pass opaque to all callbacks
   slirp: API is extern C
 
 Peter Maydell (2):
   slirp: Avoid marking naturally packed structs as QEMU_PACKED
   slirp: Don't mark struct ipq or struct ipasfrag as packed
 
 Samuel Thibault (3):
   slirp: Avoid unaligned 16bit memory access
   slirp: replace QEMU_BUILD_BUG_ON with G_STATIC_ASSERT
   slirp: Move g_spawn_async_with_fds_qemu compatibility to slirp/
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEE5h27FdQXK97JfpLZ21UOifD6VPMFAlxcOoEACgkQ21UOifD6
 VPMXKRAAh30w8FcQVSTdnc1LXTbHaaWX0onlvqNpDNsoG8bUx9wacHYuLmuQ6v/w
 7VcrFeCyB0iEs4FZqLfB7eiyhTBzUgtDkjfqPzOq887xYv2Feml3ULLlFEtHRzPd
 ht+lYiOzF3XK0PUuqquYw+NhXOb5iYGOi8YfwAvuixQR72aq/yM/1QsNAq1a/xa8
 5TlymCYIDG1n7YCZlpWtCHcbo088WbAfFFeO+n/G0haunqYXdu9aha0d0QWClWJv
 LaufmdtECKeNTdm5o2HKIzluwWVujARJ0RjhkzvdUhDMvhYdw8G3S1UvG+dDIY3Z
 EqvVTqaeK7JiTrvx7tSOQ3bA/b1YXyMcWUCvVoBwGvTtiZenjXEH2eWrS8JI4OFn
 fDADP5UFBMQ4CLf5f6584fcjN9OP2Ux3e4n6tmTUO8QuuC3NS3NmuVR0Og3TcKdo
 ewdCuhQDIFo7Ez2ChzfAvIfu2j5B/PvE0MR/0y+0WSpBnSXcukYdOSe4657m+Fco
 4Ah9v7Nu/mrYAPqbGlaExQkAJJWUmR6oY1QP32/PTLZCFEsjMD7ZNOfKS0UVtZYT
 TV+thnj2nRARLJ7OwVTbiB+BliMmJLexc92tSAmUu65VgP3BEvUU1yR/lxodwX31
 9TNS3BzRNoen+oSAJAgEfpPo3HxQanhHRi8o5o+fk8kdOkwCxzA=
 =nIy1
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/thibault/tags/samuel-thibault' into staging

More work towards libslirp

Marc-André Lureau (27):
  slirp: generalize guestfwd with a callback based approach
  net/slirp: simplify checking for cmd: prefix
  net/slirp: free forwarding rules on cleanup
  net/slirp: fix leaks on forwarding rule registration error
  slirp: add callbacks for timer
  slirp: replace trace functions with DEBUG calls
  slirp: replace QEMU_PACKED with SLIRP_PACKED
  slirp: replace most qemu socket utilities with slirp own version
  slirp: replace qemu_set_nonblock()
  slirp: add unregister_poll_fd() callback
  slirp: replace qemu_notify_event() with a callback
  slirp: move QEMU state saving to a separate unit
  slirp: do not include qemu headers in libslirp.h public API header
  slirp: improve windows headers inclusion
  slirp: add slirp own version of pstrcpy
  slirp: remove qemu timer.h dependency
  slirp: remove now useless QEMU headers inclusions
  slirp: replace net/eth.h inclusion with own defines
  slirp: replace qemu qtailq with slirp own copy
  slirp: replace remaining qemu headers dependency
  slirp: prefer c99 types over BSD kind
  slirp: improve send_packet() callback
  slirp: replace global polling with per-instance & notifier
  slirp: remove slirp_instances list
  slirp: use polling callbacks, drop glib requirement
  slirp: pass opaque to all callbacks
  slirp: API is extern C

Peter Maydell (2):
  slirp: Avoid marking naturally packed structs as QEMU_PACKED
  slirp: Don't mark struct ipq or struct ipasfrag as packed

Samuel Thibault (3):
  slirp: Avoid unaligned 16bit memory access
  slirp: replace QEMU_BUILD_BUG_ON with G_STATIC_ASSERT
  slirp: Move g_spawn_async_with_fds_qemu compatibility to slirp/

# gpg: Signature made Thu 07 Feb 2019 14:02:41 GMT
# gpg:                using RSA key E61DBB15D4172BDEC97E92D9DB550E89F0FA54F3
# gpg: Good signature from "Samuel Thibault <samuel.thibault@aquilenet.fr>" [unknown]
# gpg:                 aka "Samuel Thibault <sthibault@debian.org>" [marginal]
# gpg:                 aka "Samuel Thibault <samuel.thibault@gnu.org>" [unknown]
# gpg:                 aka "Samuel Thibault <samuel.thibault@inria.fr>" [marginal]
# gpg:                 aka "Samuel Thibault <samuel.thibault@labri.fr>" [marginal]
# gpg:                 aka "Samuel Thibault <samuel.thibault@ens-lyon.org>" [marginal]
# gpg:                 aka "Samuel Thibault <samuel.thibault@u-bordeaux.fr>" [unknown]
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg:          It is not certain that the signature belongs to the owner.
# Primary key fingerprint: 900C B024 B679 31D4 0F82  304B D017 8C76 7D06 9EE6
#      Subkey fingerprint: E61D BB15 D417 2BDE C97E  92D9 DB55 0E89 F0FA 54F3

* remotes/thibault/tags/samuel-thibault: (32 commits)
  slirp: API is extern C
  slirp: pass opaque to all callbacks
  slirp: use polling callbacks, drop glib requirement
  slirp: remove slirp_instances list
  slirp: replace global polling with per-instance & notifier
  slirp: improve send_packet() callback
  slirp: prefer c99 types over BSD kind
  slirp: replace remaining qemu headers dependency
  slirp: Move g_spawn_async_with_fds_qemu compatibility to slirp/
  slirp: replace QEMU_BUILD_BUG_ON with G_STATIC_ASSERT
  slirp: replace qemu qtailq with slirp own copy
  slirp: replace net/eth.h inclusion with own defines
  slirp: remove now useless QEMU headers inclusions
  slirp: remove qemu timer.h dependency
  slirp: add slirp own version of pstrcpy
  slirp: improve windows headers inclusion
  slirp: do not include qemu headers in libslirp.h public API header
  slirp: move QEMU state saving to a separate unit
  slirp: replace qemu_notify_event() with a callback
  slirp: add unregister_poll_fd() callback
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2019-02-07 18:53:25 +00:00
commit e47f81b617
57 changed files with 1869 additions and 1060 deletions

View file

@ -192,7 +192,6 @@ trace-events-subdirs += net
trace-events-subdirs += qapi
trace-events-subdirs += qom
trace-events-subdirs += scsi
trace-events-subdirs += slirp
trace-events-subdirs += target/arm
trace-events-subdirs += target/i386
trace-events-subdirs += target/mips

View file

@ -83,63 +83,6 @@ static inline gboolean g_strv_contains_qemu(const gchar *const *strv,
}
#define g_strv_contains(a, b) g_strv_contains_qemu(a, b)
#if !GLIB_CHECK_VERSION(2, 58, 0)
typedef struct QemuGSpawnFds {
GSpawnChildSetupFunc child_setup;
gpointer user_data;
gint stdin_fd;
gint stdout_fd;
gint stderr_fd;
} QemuGSpawnFds;
static inline void
qemu_gspawn_fds_setup(gpointer user_data)
{
QemuGSpawnFds *q = (QemuGSpawnFds *)user_data;
dup2(q->stdin_fd, 0);
dup2(q->stdout_fd, 1);
dup2(q->stderr_fd, 2);
q->child_setup(q->user_data);
}
#endif
static inline gboolean
g_spawn_async_with_fds_qemu(const gchar *working_directory,
gchar **argv,
gchar **envp,
GSpawnFlags flags,
GSpawnChildSetupFunc child_setup,
gpointer user_data,
GPid *child_pid,
gint stdin_fd,
gint stdout_fd,
gint stderr_fd,
GError **error)
{
#if GLIB_CHECK_VERSION(2, 58, 0)
return g_spawn_async_with_fds(working_directory, argv, envp, flags,
child_setup, user_data,
child_pid, stdin_fd, stdout_fd, stderr_fd,
error);
#else
QemuGSpawnFds setup = {
.child_setup = child_setup,
.user_data = user_data,
.stdin_fd = stdin_fd,
.stdout_fd = stdout_fd,
.stderr_fd = stderr_fd,
};
return g_spawn_async(working_directory, argv, envp, flags,
qemu_gspawn_fds_setup, &setup,
child_pid, error);
#endif
}
#define g_spawn_async_with_fds(wd, argv, env, f, c, d, p, ifd, ofd, efd, err) \
g_spawn_async_with_fds_qemu(wd, argv, env, f, c, d, p, ifd, ofd, efd, err)
#if defined(_WIN32) && !GLIB_CHECK_VERSION(2, 50, 0)
/*
* g_poll has a problem on Windows when using

View file

@ -146,7 +146,7 @@ ssize_t qemu_sendv_packet(NetClientState *nc, const struct iovec *iov,
int iovcnt);
ssize_t qemu_sendv_packet_async(NetClientState *nc, const struct iovec *iov,
int iovcnt, NetPacketSent *sent_cb);
void qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size);
ssize_t qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size);
ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size);
ssize_t qemu_send_packet_async(NetClientState *nc, const uint8_t *buf,
int size, NetPacketSent *sent_cb);

View file

@ -302,4 +302,19 @@ void qemu_fd_register(int fd);
QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque);
void qemu_bh_schedule_idle(QEMUBH *bh);
enum {
MAIN_LOOP_POLL_FILL,
MAIN_LOOP_POLL_ERR,
MAIN_LOOP_POLL_OK,
};
typedef struct MainLoopPoll {
int state;
uint32_t timeout;
GArray *pollfds;
} MainLoopPoll;
void main_loop_poll_add_notifier(Notifier *notify);
void main_loop_poll_remove_notifier(Notifier *notify);
#endif

View file

@ -668,9 +668,9 @@ ssize_t qemu_send_packet_async(NetClientState *sender,
buf, size, sent_cb);
}
void qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size)
ssize_t qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size)
{
qemu_send_packet_async(nc, buf, size, NULL);
return qemu_send_packet_async(nc, buf, size, NULL);
}
ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size)

View file

@ -75,14 +75,23 @@ struct slirp_config_str {
char str[1024];
};
struct GuestFwd {
CharBackend hd;
struct in_addr server;
int port;
Slirp *slirp;
};
typedef struct SlirpState {
NetClientState nc;
QTAILQ_ENTRY(SlirpState) entry;
Slirp *slirp;
Notifier poll_notifier;
Notifier exit_notifier;
#ifndef _WIN32
gchar *smb_dir;
#endif
GSList *fwd;
} SlirpState;
static struct slirp_config_str *slirp_configs;
@ -100,11 +109,12 @@ static void slirp_smb_cleanup(SlirpState *s);
static inline void slirp_smb_cleanup(SlirpState *s) { }
#endif
static void net_slirp_output(void *opaque, const uint8_t *pkt, int pkt_len)
static ssize_t net_slirp_send_packet(const void *pkt, size_t pkt_len,
void *opaque)
{
SlirpState *s = opaque;
qemu_send_packet(&s->nc, pkt, pkt_len);
return qemu_send_packet(&s->nc, pkt, pkt_len);
}
static ssize_t net_slirp_receive(NetClientState *nc, const uint8_t *buf, size_t size)
@ -122,10 +132,20 @@ static void slirp_smb_exit(Notifier *n, void *data)
slirp_smb_cleanup(s);
}
static void slirp_free_fwd(gpointer data)
{
struct GuestFwd *fwd = data;
qemu_chr_fe_deinit(&fwd->hd, true);
g_free(data);
}
static void net_slirp_cleanup(NetClientState *nc)
{
SlirpState *s = DO_UPCAST(SlirpState, nc, nc);
g_slist_free_full(s->fwd, slirp_free_fwd);
main_loop_poll_remove_notifier(&s->poll_notifier);
slirp_cleanup(s->slirp);
if (s->exit_notifier.notify) {
qemu_remove_exit_notifier(&s->exit_notifier);
@ -141,22 +161,148 @@ static NetClientInfo net_slirp_info = {
.cleanup = net_slirp_cleanup,
};
static void net_slirp_guest_error(const char *msg)
static void net_slirp_guest_error(const char *msg, void *opaque)
{
qemu_log_mask(LOG_GUEST_ERROR, "%s", msg);
}
static int64_t net_slirp_clock_get_ns(void)
static int64_t net_slirp_clock_get_ns(void *opaque)
{
return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
}
static void *net_slirp_timer_new(SlirpTimerCb cb,
void *cb_opaque, void *opaque)
{
return timer_new_full(NULL, QEMU_CLOCK_VIRTUAL,
SCALE_MS, QEMU_TIMER_ATTR_EXTERNAL,
cb, cb_opaque);
}
static void net_slirp_timer_free(void *timer, void *opaque)
{
timer_del(timer);
timer_free(timer);
}
static void net_slirp_timer_mod(void *timer, int64_t expire_timer,
void *opaque)
{
timer_mod(timer, expire_timer);
}
static void net_slirp_register_poll_fd(int fd, void *opaque)
{
qemu_fd_register(fd);
}
static void net_slirp_unregister_poll_fd(int fd, void *opaque)
{
/* no qemu_fd_unregister */
}
static void net_slirp_notify(void *opaque)
{
qemu_notify_event();
}
static const SlirpCb slirp_cb = {
.output = net_slirp_output,
.send_packet = net_slirp_send_packet,
.guest_error = net_slirp_guest_error,
.clock_get_ns = net_slirp_clock_get_ns,
.timer_new = net_slirp_timer_new,
.timer_free = net_slirp_timer_free,
.timer_mod = net_slirp_timer_mod,
.register_poll_fd = net_slirp_register_poll_fd,
.unregister_poll_fd = net_slirp_unregister_poll_fd,
.notify = net_slirp_notify,
};
static int slirp_poll_to_gio(int events)
{
int ret = 0;
if (events & SLIRP_POLL_IN) {
ret |= G_IO_IN;
}
if (events & SLIRP_POLL_OUT) {
ret |= G_IO_OUT;
}
if (events & SLIRP_POLL_PRI) {
ret |= G_IO_PRI;
}
if (events & SLIRP_POLL_ERR) {
ret |= G_IO_ERR;
}
if (events & SLIRP_POLL_HUP) {
ret |= G_IO_HUP;
}
return ret;
}
static int net_slirp_add_poll(int fd, int events, void *opaque)
{
GArray *pollfds = opaque;
GPollFD pfd = {
.fd = fd,
.events = slirp_poll_to_gio(events),
};
int idx = pollfds->len;
g_array_append_val(pollfds, pfd);
return idx;
}
static int slirp_gio_to_poll(int events)
{
int ret = 0;
if (events & G_IO_IN) {
ret |= SLIRP_POLL_IN;
}
if (events & G_IO_OUT) {
ret |= SLIRP_POLL_OUT;
}
if (events & G_IO_PRI) {
ret |= SLIRP_POLL_PRI;
}
if (events & G_IO_ERR) {
ret |= SLIRP_POLL_ERR;
}
if (events & G_IO_HUP) {
ret |= SLIRP_POLL_HUP;
}
return ret;
}
static int net_slirp_get_revents(int idx, void *opaque)
{
GArray *pollfds = opaque;
return slirp_gio_to_poll(g_array_index(pollfds, GPollFD, idx).revents);
}
static void net_slirp_poll_notify(Notifier *notifier, void *data)
{
MainLoopPoll *poll = data;
SlirpState *s = container_of(notifier, SlirpState, poll_notifier);
switch (poll->state) {
case MAIN_LOOP_POLL_FILL:
slirp_pollfds_fill(s->slirp, &poll->timeout,
net_slirp_add_poll, poll->pollfds);
break;
case MAIN_LOOP_POLL_OK:
case MAIN_LOOP_POLL_ERR:
slirp_pollfds_poll(s->slirp, poll->state == MAIN_LOOP_POLL_ERR,
net_slirp_get_revents, poll->pollfds);
break;
default:
g_assert_not_reached();
}
}
static int net_slirp_init(NetClientState *peer, const char *model,
const char *name, int restricted,
bool ipv4, const char *vnetwork, const char *vhost,
@ -377,6 +523,9 @@ static int net_slirp_init(NetClientState *peer, const char *model,
&slirp_cb, s);
QTAILQ_INSERT_TAIL(&slirp_stacks, s, entry);
s->poll_notifier.notify = net_slirp_poll_notify;
main_loop_poll_add_notifier(&s->poll_notifier);
for (config = slirp_configs; config; config = config->next) {
if (config->flags & SLIRP_CFG_HOSTFWD) {
if (slirp_hostfwd(s, config->str, errp) < 0) {
@ -704,8 +853,8 @@ static int slirp_smb(SlirpState* s, const char *exported_dir,
CONFIG_SMBD_COMMAND, s->smb_dir, smb_conf);
g_free(smb_conf);
if (slirp_add_exec(s->slirp, NULL, smb_cmdline, &vserver_addr, 139) < 0 ||
slirp_add_exec(s->slirp, NULL, smb_cmdline, &vserver_addr, 445) < 0) {
if (slirp_add_exec(s->slirp, smb_cmdline, &vserver_addr, 139) < 0 ||
slirp_add_exec(s->slirp, smb_cmdline, &vserver_addr, 445) < 0) {
slirp_smb_cleanup(s);
g_free(smb_cmdline);
error_setg(errp, "Conflicting/invalid smbserver address");
@ -717,13 +866,6 @@ static int slirp_smb(SlirpState* s, const char *exported_dir,
#endif /* !defined(_WIN32) */
struct GuestFwd {
CharBackend hd;
struct in_addr server;
int port;
Slirp *slirp;
};
static int guestfwd_can_read(void *opaque)
{
struct GuestFwd *fwd = opaque;
@ -736,6 +878,11 @@ static void guestfwd_read(void *opaque, const uint8_t *buf, int size)
slirp_socket_recv(fwd->slirp, fwd->server, fwd->port, buf, size);
}
static ssize_t guestfwd_write(const void *buf, size_t len, void *chr)
{
return qemu_chr_fe_write_all(chr, buf, len);
}
static int slirp_guestfwd(SlirpState *s, const char *config_str, Error **errp)
{
struct in_addr server = { .s_addr = 0 };
@ -768,8 +915,8 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str, Error **errp)
snprintf(buf, sizeof(buf), "guestfwd.tcp.%d", port);
if ((strlen(p) > 4) && !strncmp(p, "cmd:", 4)) {
if (slirp_add_exec(s->slirp, NULL, &p[4], &server, port) < 0) {
if (g_str_has_prefix(p, "cmd:")) {
if (slirp_add_exec(s->slirp, &p[4], &server, port) < 0) {
error_setg(errp, "Conflicting/invalid host:port in guest "
"forwarding rule '%s'", config_str);
return -1;
@ -792,13 +939,16 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str, Error **errp)
qemu_chr_fe_init(&fwd->hd, chr, &err);
if (err) {
error_propagate(errp, err);
object_unparent(OBJECT(chr));
g_free(fwd);
return -1;
}
if (slirp_add_exec(s->slirp, &fwd->hd, NULL, &server, port) < 0) {
if (slirp_add_guestfwd(s->slirp, guestfwd_write, &fwd->hd,
&server, port) < 0) {
error_setg(errp, "Conflicting/invalid host:port in guest "
"forwarding rule '%s'", config_str);
qemu_chr_fe_deinit(&fwd->hd, true);
g_free(fwd);
return -1;
}
@ -808,6 +958,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str, Error **errp)
qemu_chr_fe_set_handlers(&fwd->hd, guestfwd_can_read, guestfwd_read,
NULL, NULL, fwd, NULL, true);
s->fwd = g_slist_append(s->fwd, fwd);
}
return 0;

View file

@ -20,6 +20,7 @@ slirp.mo-objs = \
sbuf.o \
slirp.o \
socket.o \
state.o \
tcp_input.o \
tcp_output.o \
tcp_subr.o \
@ -27,6 +28,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

View file

@ -22,9 +22,10 @@
* THE SOFTWARE.
*/
#include "qemu/osdep.h"
#include "slirp.h"
#include <string.h>
void arp_table_add(Slirp *slirp, uint32_t ip_addr, uint8_t ethaddr[ETH_ALEN])
{
const uint32_t broadcast_addr =

View file

@ -21,7 +21,6 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "qemu/osdep.h"
#include "slirp.h"
#if defined(_WIN32)

View file

@ -30,7 +30,6 @@
* in_cksum.c,v 1.2 1994/08/02 07:48:16 davidg Exp
*/
#include "qemu/osdep.h"
#include "slirp.h"
/*

View file

@ -8,9 +8,10 @@
#ifndef DEBUG_H_
#define DEBUG_H_
#define DBG_CALL 0x1
#define DBG_MISC 0x2
#define DBG_ERROR 0x4
#define DBG_CALL (1 << 0)
#define DBG_MISC (1 << 1)
#define DBG_ERROR (1 << 2)
#define DBG_TFTP (1 << 3)
extern int slirp_debug;
@ -38,4 +39,10 @@ extern int slirp_debug;
} \
} while (0)
#define DEBUG_TFTP(fmt, ...) do { \
if (G_UNLIKELY(slirp_debug & DBG_TFTP)) { \
g_debug(fmt, ##__VA_ARGS__); \
} \
} while (0)
#endif /* DEBUG_H_ */

View file

@ -20,8 +20,6 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h"
#include "qemu/log.h"
#include "slirp.h"
#include "dhcpv6.h"
@ -61,7 +59,7 @@ static int dhcpv6_parse_info_request(Slirp *slirp, uint8_t *odata, int olen,
int len = odata[2] << 8 | odata[3];
if (len + 4 > olen) {
slirp->cb->guest_error("Guest sent bad DHCPv6 packet!");
slirp->cb->guest_error("Guest sent bad DHCPv6 packet!", slirp->opaque);
return -E2BIG;
}

View file

@ -22,7 +22,6 @@
* THE SOFTWARE.
*/
#include "qemu/osdep.h"
#include "slirp.h"
static const uint8_t RFC3397_OPT_DOMAIN_SEARCH = 119;

View file

@ -5,9 +5,7 @@
* terms and conditions of the copyright.
*/
#include "qemu/osdep.h"
#include "slirp.h"
#include "qemu/timer.h"
static void
ifs_insque(struct mbuf *ifm, struct mbuf *ifmhead)
@ -148,7 +146,7 @@ diddit:
*/
void if_start(Slirp *slirp)
{
uint64_t now = slirp->cb->clock_get_ns();
uint64_t now = slirp->cb->clock_get_ns(slirp->opaque);
bool from_batchq = false;
struct mbuf *ifm, *ifm_next, *ifqt;

View file

@ -89,7 +89,7 @@ struct ip {
uint8_t ip_p; /* protocol */
uint16_t ip_sum; /* checksum */
struct in_addr ip_src,ip_dst; /* source and dest address */
} QEMU_PACKED;
} SLIRP_PACKED;
#define IP_MAXPACKET 65535 /* maximum packet size */
@ -151,7 +151,7 @@ struct ip_timestamp {
n_long ipt_time;
} ipt_ta[1];
} ipt_timestamp;
} QEMU_PACKED;
} SLIRP_PACKED;
/* flag bits for ipt_flg */
#define IPOPT_TS_TSONLY 0 /* timestamps only */
@ -181,11 +181,11 @@ struct ip_timestamp {
struct mbuf_ptr {
struct mbuf *mptr;
uint32_t dummy;
} QEMU_PACKED;
} SLIRP_PACKED;
#else
struct mbuf_ptr {
struct mbuf *mptr;
} QEMU_PACKED;
} SLIRP_PACKED;
#endif
struct qlink {
void *next, *prev;
@ -201,7 +201,7 @@ struct ipovly {
uint16_t ih_len; /* protocol length */
struct in_addr ih_src; /* source internet address */
struct in_addr ih_dst; /* destination internet address */
} QEMU_PACKED;
} SLIRP_PACKED;
/*
* Ip reassembly queue structure. Each fragment
@ -217,7 +217,7 @@ struct ipq {
uint8_t ipq_p; /* protocol of this fragment */
uint16_t ipq_id; /* sequence id for reassembly */
struct in_addr ipq_src,ipq_dst;
} QEMU_PACKED;
};
/*
* Ip header, when holding a fragment.
@ -227,7 +227,10 @@ struct ipq {
struct ipasfrag {
struct qlink ipf_link;
struct ip ipf_ip;
} QEMU_PACKED;
};
G_STATIC_ASSERT(offsetof(struct ipq, frag_link) ==
offsetof(struct ipasfrag, ipf_link));
#define ipf_off ipf_ip.ip_off
#define ipf_tos ipf_ip.ip_tos

View file

@ -7,7 +7,7 @@
#define SLIRP_IP6_H
#include <glib.h>
#include "net/eth.h"
#include <string.h>
#define ALLNODES_MULTICAST { .s6_addr = \
{ 0xff, 0x02, 0x00, 0x00,\
@ -133,7 +133,7 @@ struct ip6 {
uint8_t ip_nh; /* next header */
uint8_t ip_hl; /* hop limit */
struct in6_addr ip_src, ip_dst; /* source and dest address */
} QEMU_PACKED;
};
/*
* IPv6 pseudo-header used by upper-layer protocols
@ -145,7 +145,15 @@ struct ip6_pseudohdr {
uint16_t ih_zero_hi; /* zero */
uint8_t ih_zero_lo; /* zero */
uint8_t ih_nh; /* next header */
} QEMU_PACKED;
};
/*
* We don't want to mark these ip6 structs as packed as they are naturally
* correctly aligned; instead assert that there is no stray padding.
* If we marked the struct as packed then we would be unable to take
* the address of any of the fields in it.
*/
G_STATIC_ASSERT(sizeof(struct ip6) == 40);
G_STATIC_ASSERT(sizeof(struct ip6_pseudohdr) == 40);
#endif

View file

@ -3,12 +3,8 @@
* Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne.
*/
#include "qemu/osdep.h"
#include "slirp.h"
#include "ip6_icmp.h"
#include "qemu/timer.h"
#include "qemu/error-report.h"
#include "qemu/log.h"
#define NDP_Interval g_rand_int_range(slirp->grand, \
NDP_MinRtrAdvInterval, NDP_MaxRtrAdvInterval)
@ -16,8 +12,10 @@
static void ra_timer_handler(void *opaque)
{
Slirp *slirp = opaque;
timer_mod(slirp->ra_timer,
slirp->cb->clock_get_ns() / SCALE_MS + NDP_Interval);
slirp->cb->timer_mod(slirp->ra_timer,
slirp->cb->clock_get_ns(slirp->opaque) / SCALE_MS + NDP_Interval,
slirp->opaque);
ndp_send_ra(slirp);
}
@ -27,11 +25,10 @@ void icmp6_init(Slirp *slirp)
return;
}
slirp->ra_timer = timer_new_full(NULL, QEMU_CLOCK_VIRTUAL,
SCALE_MS, QEMU_TIMER_ATTR_EXTERNAL,
ra_timer_handler, slirp);
timer_mod(slirp->ra_timer,
slirp->cb->clock_get_ns() / SCALE_MS + NDP_Interval);
slirp->ra_timer = slirp->cb->timer_new(ra_timer_handler, slirp, slirp->opaque);
slirp->cb->timer_mod(slirp->ra_timer,
slirp->cb->clock_get_ns(slirp->opaque) / SCALE_MS + NDP_Interval,
slirp->opaque);
}
void icmp6_cleanup(Slirp *slirp)
@ -40,8 +37,7 @@ void icmp6_cleanup(Slirp *slirp)
return;
}
timer_del(slirp->ra_timer);
timer_free(slirp->ra_timer);
slirp->cb->timer_free(slirp->ra_timer, slirp->opaque);
}
static void icmp6_send_echoreply(struct mbuf *m, Slirp *slirp, struct ip6 *ip,
@ -340,7 +336,8 @@ static void ndp_input(struct mbuf *m, Slirp *slirp, struct ip6 *ip,
case ICMP6_NDP_RA:
DEBUG_CALL(" type = Router Advertisement");
slirp->cb->guest_error("Warning: guest sent NDP RA, but shouldn't");
slirp->cb->guest_error("Warning: guest sent NDP RA, but shouldn't",
slirp->opaque);
break;
case ICMP6_NDP_NS:
@ -374,7 +371,7 @@ static void ndp_input(struct mbuf *m, Slirp *slirp, struct ip6 *ip,
case ICMP6_NDP_REDIRECT:
DEBUG_CALL(" type = Redirect");
slirp->cb->guest_error(
"Warning: guest sent NDP REDIRECT, but shouldn't");
"Warning: guest sent NDP REDIRECT, but shouldn't", slirp->opaque);
break;
}
}

View file

@ -48,12 +48,16 @@ struct ndp_ra { /* Router Advertisement Message */
uint16_t lifetime; /* Router Lifetime */
uint32_t reach_time; /* Reachable Time */
uint32_t retrans_time; /* Retrans Timer */
} QEMU_PACKED;
};
G_STATIC_ASSERT(sizeof(struct ndp_ra) == 12);
struct ndp_ns { /* Neighbor Solicitation Message */
uint32_t reserved;
struct in6_addr target; /* Target Address */
} QEMU_PACKED;
};
G_STATIC_ASSERT(sizeof(struct ndp_ns) == 20);
struct ndp_na { /* Neighbor Advertisement Message */
#if G_BYTE_ORDER == G_BIG_ENDIAN
@ -72,13 +76,17 @@ struct ndp_na { /* Neighbor Advertisement Message */
reserved_lo:24;
#endif
struct in6_addr target; /* Target Address */
} QEMU_PACKED;
};
G_STATIC_ASSERT(sizeof(struct ndp_na) == 20);
struct ndp_redirect {
uint32_t reserved;
struct in6_addr target; /* Target Address */
struct in6_addr dest; /* Destination Address */
} QEMU_PACKED;
};
G_STATIC_ASSERT(sizeof(struct ndp_redirect) == 36);
/*
* Structure of an icmpv6 header.
@ -103,7 +111,9 @@ struct icmp6 {
#define icmp6_nns icmp6_body.ndp_ns
#define icmp6_nna icmp6_body.ndp_na
#define icmp6_redirect icmp6_body.ndp_redirect
} QEMU_PACKED;
};
G_STATIC_ASSERT(sizeof(struct icmp6) == 40);
#define ICMP6_MINLEN 4
#define ICMP6_ERROR_MINLEN 8
@ -134,16 +144,16 @@ struct ndpopt {
uint32_t pref_lt; /* Preferred Lifetime */
uint32_t reserved2;
struct in6_addr prefix;
} QEMU_PACKED prefixinfo;
} SLIRP_PACKED prefixinfo;
#define ndpopt_prefixinfo ndpopt_body.prefixinfo
struct rdnss {
uint16_t reserved;
uint32_t lifetime;
struct in6_addr addr;
} QEMU_PACKED rdnss;
} SLIRP_PACKED rdnss;
#define ndpopt_rdnss ndpopt_body.rdnss
} ndpopt_body;
} QEMU_PACKED;
} SLIRP_PACKED;
/* NDP options type */
#define NDPOPT_LINKLAYER_SOURCE 1 /* Source Link-Layer Address */

View file

@ -3,7 +3,6 @@
* Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne.
*/
#include "qemu/osdep.h"
#include "slirp.h"
#include "ip6_icmp.h"

View file

@ -3,8 +3,6 @@
* Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne.
*/
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "slirp.h"
/* Number of packets queued before we start sending

View file

@ -30,7 +30,6 @@
* ip_icmp.c,v 1.7 1995/05/30 08:09:42 rgrimes Exp
*/
#include "qemu/osdep.h"
#include "slirp.h"
#include "ip_icmp.h"
@ -83,7 +82,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 +113,8 @@ static int icmp_send(struct socket *so, struct mbuf *m, int hlen)
void icmp_detach(struct socket *so)
{
closesocket(so->s);
so->slirp->cb->unregister_poll_fd(so->s, so->slirp->opaque);
slirp_closesocket(so->s);
sofree(so);
}
@ -240,7 +240,7 @@ end_error:
#define ICMP_MAXDATALEN (IP_MSS-28)
void
icmp_send_error(struct mbuf *msrc, u_char type, u_char code, int minsize,
icmp_send_error(struct mbuf *msrc, uint8_t type, uint8_t code, int minsize,
const char *message)
{
unsigned hlen, shlen, s_ip_len;
@ -388,7 +388,7 @@ icmp_reflect(struct mbuf *m)
* Strip out original options by copying rest of first
* mbuf's data back, and adjust the IP length.
*/
memmove((caddr_t)(ip + 1), (caddr_t)ip + hlen,
memmove((char *)(ip + 1), (char *)ip + hlen,
(unsigned )(m->m_len - hlen));
hlen -= optlen;
ip->ip_hl = hlen >> 2;
@ -412,7 +412,7 @@ void icmp_receive(struct socket *so)
struct mbuf *m = so->so_m;
struct ip *ip = mtod(m, struct ip *);
int hlen = ip->ip_hl << 2;
u_char error_code;
uint8_t error_code;
struct icmp *icp;
int id, len;
@ -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

View file

@ -44,22 +44,22 @@ typedef uint32_t n_time;
* Structure of an icmp header.
*/
struct icmp {
u_char icmp_type; /* type of message, see below */
u_char icmp_code; /* type sub code */
u_short icmp_cksum; /* ones complement cksum of struct */
uint8_t icmp_type; /* type of message, see below */
uint8_t icmp_code; /* type sub code */
uint16_t icmp_cksum; /* ones complement cksum of struct */
union {
u_char ih_pptr; /* ICMP_PARAMPROB */
uint8_t ih_pptr; /* ICMP_PARAMPROB */
struct in_addr ih_gwaddr; /* ICMP_REDIRECT */
struct ih_idseq {
u_short icd_id;
u_short icd_seq;
uint16_t icd_id;
uint16_t icd_seq;
} ih_idseq;
int ih_void;
/* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */
struct ih_pmtu {
u_short ipm_void;
u_short ipm_nextmtu;
uint16_t ipm_void;
uint16_t ipm_nextmtu;
} ih_pmtu;
} icmp_hun;
#define icmp_pptr icmp_hun.ih_pptr
@ -156,7 +156,7 @@ struct icmp {
void icmp_init(Slirp *slirp);
void icmp_cleanup(Slirp *slirp);
void icmp_input(struct mbuf *, int);
void icmp_send_error(struct mbuf *msrc, u_char type, u_char code, int minsize,
void icmp_send_error(struct mbuf *msrc, uint8_t type, uint8_t code, int minsize,
const char *message);
void icmp_reflect(struct mbuf *);
void icmp_receive(struct socket *so);

View file

@ -38,7 +38,6 @@
* terms and conditions of the copyright.
*/
#include "qemu/osdep.h"
#include "slirp.h"
#include "ip_icmp.h"
@ -459,11 +458,11 @@ ip_stripoptions(register struct mbuf *m, struct mbuf *mopt)
{
register int i;
struct ip *ip = mtod(m, struct ip *);
register caddr_t opts;
register char *opts;
int olen;
olen = (ip->ip_hl<<2) - sizeof (struct ip);
opts = (caddr_t)(ip + 1);
opts = (char *)(ip + 1);
i = m->m_len - (sizeof (struct ip) + olen);
memcpy(opts, opts + olen, (unsigned)i);
m->m_len -= olen;

View file

@ -38,7 +38,6 @@
* terms and conditions of the copyright.
*/
#include "qemu/osdep.h"
#include "slirp.h"
/* Number of packets queued before we start sending

View file

@ -1,22 +1,64 @@
#ifndef LIBSLIRP_H
#define LIBSLIRP_H
#include "qemu-common.h"
#include <stdint.h>
#include <stdbool.h>
#ifdef _WIN32
#include <winsock2.h>
#include <in6addr.h>
#else
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef struct Slirp Slirp;
enum {
SLIRP_POLL_IN = 1 << 0,
SLIRP_POLL_OUT = 1 << 1,
SLIRP_POLL_PRI = 1 << 2,
SLIRP_POLL_ERR = 1 << 3,
SLIRP_POLL_HUP = 1 << 4,
};
typedef ssize_t (*SlirpWriteCb)(const void *buf, size_t len, void *opaque);
typedef void (*SlirpTimerCb)(void *opaque);
typedef int (*SlirpAddPollCb)(int fd, int events, void *opaque);
typedef int (*SlirpGetREventsCb)(int idx, void *opaque);
/*
* Callbacks from slirp
*
* The opaque parameter comes from the opaque parameter given to slirp_init().
*/
typedef struct SlirpCb {
/* Send an ethernet frame to the guest network. */
void (*output)(void *opaque, const uint8_t *pkt, int pkt_len);
/*
* Send an ethernet frame to the guest network. The opaque
* parameter is the one given to slirp_init(). The function
* doesn't need to send all the data and may return <len (no
* buffering is done on libslirp side, so the data will be dropped
* in this case). <0 reports an IO error.
*/
SlirpWriteCb send_packet;
/* Print a message for an error due to guest misbehavior. */
void (*guest_error)(const char *msg);
void (*guest_error)(const char *msg, void *opaque);
/* Return the virtual clock value in nanoseconds */
int64_t (*clock_get_ns)(void);
int64_t (*clock_get_ns)(void *opaque);
/* Create a new timer with the given callback and opaque data */
void *(*timer_new)(SlirpTimerCb cb, void *cb_opaque, void *opaque);
/* Remove and free a timer */
void (*timer_free)(void *timer, void *opaque);
/* Modify a timer to expire at @expire_time */
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);
/* Unregister a fd */
void (*unregister_poll_fd)(int fd, void *opaque);
/* Kick the io-thread, to signal that new events may be processed */
void (*notify)(void *opaque);
} SlirpCb;
@ -34,9 +76,11 @@ Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork,
void *opaque);
void slirp_cleanup(Slirp *slirp);
void slirp_pollfds_fill(GArray *pollfds, uint32_t *timeout);
void slirp_pollfds_fill(Slirp *slirp, uint32_t *timeout,
SlirpAddPollCb add_poll, void *opaque);
void slirp_pollfds_poll(GArray *pollfds, int select_error);
void slirp_pollfds_poll(Slirp *slirp, int select_error,
SlirpGetREventsCb get_revents, void *opaque);
void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len);
@ -45,7 +89,9 @@ int slirp_add_hostfwd(Slirp *slirp, int is_udp,
struct in_addr guest_addr, int guest_port);
int slirp_remove_hostfwd(Slirp *slirp, int is_udp,
struct in_addr host_addr, int host_port);
int slirp_add_exec(Slirp *slirp, void *chardev, const char *cmdline,
int slirp_add_exec(Slirp *slirp, const char *cmdline,
struct in_addr *guest_addr, int guest_port);
int slirp_add_guestfwd(Slirp *slirp, SlirpWriteCb write_cb, void *opaque,
struct in_addr *guest_addr, int guest_port);
char *slirp_connection_info(Slirp *slirp);
@ -54,5 +100,8 @@ void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr,
int guest_port, const uint8_t *buf, int size);
size_t slirp_socket_can_recv(Slirp *slirp, struct in_addr guest_addr,
int guest_port);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* LIBSLIRP_H */

View file

@ -8,7 +8,7 @@
#ifndef SLIRP_MAIN_H
#define SLIRP_MAIN_H
extern u_int curtime;
extern unsigned curtime;
extern struct in_addr loopback_addr;
extern unsigned long loopback_mask;

View file

@ -15,7 +15,6 @@
* the flags
*/
#include "qemu/osdep.h"
#include "slirp.h"
#define MBUF_THRESH 30

View file

@ -85,7 +85,7 @@ struct mbuf {
int m_size; /* Size of mbuf, from m_dat or m_ext */
struct socket *m_so;
caddr_t m_data; /* Current location of data */
char *m_data; /* Current location of data */
int m_len; /* Amount of data in this mbuf, from m_data */
Slirp *slirp;

View file

@ -5,11 +5,7 @@
* terms and conditions of the copyright.
*/
#include "qemu/osdep.h"
#include "slirp.h"
#include "libslirp.h"
#include "qemu/error-report.h"
#include "qemu/main-loop.h"
inline void
insque(void *a, void *b)
@ -32,24 +28,33 @@ remque(void *a)
element->qh_rlink = NULL;
}
int add_exec(struct gfwd_list **ex_ptr, void *chardev, const char *cmdline,
struct gfwd_list *
add_guestfwd(struct gfwd_list **ex_ptr,
SlirpWriteCb write_cb, void *opaque,
struct in_addr addr, int port)
{
struct gfwd_list *tmp_ptr;
struct gfwd_list *f = g_new0(struct gfwd_list, 1);
tmp_ptr = *ex_ptr;
*ex_ptr = g_new0(struct gfwd_list, 1);
(*ex_ptr)->ex_fport = port;
(*ex_ptr)->ex_addr = addr;
if (chardev) {
(*ex_ptr)->ex_chardev = chardev;
} else {
(*ex_ptr)->ex_exec = g_strdup(cmdline);
}
(*ex_ptr)->ex_next = tmp_ptr;
return 0;
f->write_cb = write_cb;
f->opaque = opaque;
f->ex_fport = port;
f->ex_addr = addr;
f->ex_next = *ex_ptr;
*ex_ptr = f;
return f;
}
struct gfwd_list *
add_exec(struct gfwd_list **ex_ptr, const char *cmdline,
struct in_addr addr, int port)
{
struct gfwd_list *f = add_guestfwd(ex_ptr, NULL, NULL, addr, port);
f->ex_exec = g_strdup(cmdline);
return f;
}
static int
slirp_socketpair_with_oob(int sv[2])
@ -63,14 +68,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;
}
@ -93,16 +98,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;
}
@ -115,6 +120,68 @@ fork_exec_child_setup(gpointer data)
#endif
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#if !GLIB_CHECK_VERSION(2, 58, 0)
typedef struct SlirpGSpawnFds {
GSpawnChildSetupFunc child_setup;
gpointer user_data;
gint stdin_fd;
gint stdout_fd;
gint stderr_fd;
} SlirpGSpawnFds;
static inline void
slirp_gspawn_fds_setup(gpointer user_data)
{
SlirpGSpawnFds *q = (SlirpGSpawnFds *)user_data;
dup2(q->stdin_fd, 0);
dup2(q->stdout_fd, 1);
dup2(q->stderr_fd, 2);
q->child_setup(q->user_data);
}
#endif
static inline gboolean
g_spawn_async_with_fds_slirp(const gchar *working_directory,
gchar **argv,
gchar **envp,
GSpawnFlags flags,
GSpawnChildSetupFunc child_setup,
gpointer user_data,
GPid *child_pid,
gint stdin_fd,
gint stdout_fd,
gint stderr_fd,
GError **error)
{
#if GLIB_CHECK_VERSION(2, 58, 0)
return g_spawn_async_with_fds(working_directory, argv, envp, flags,
child_setup, user_data,
child_pid, stdin_fd, stdout_fd, stderr_fd,
error);
#else
SlirpGSpawnFds setup = {
.child_setup = child_setup,
.user_data = user_data,
.stdin_fd = stdin_fd,
.stdout_fd = stdout_fd,
.stderr_fd = stderr_fd,
};
return g_spawn_async(working_directory, argv, envp, flags,
slirp_gspawn_fds_setup, &setup,
child_pid, error);
#endif
}
#define g_spawn_async_with_fds(wd, argv, env, f, c, d, p, ifd, ofd, efd, err) \
g_spawn_async_with_fds_slirp(wd, argv, env, f, c, d, p, ifd, ofd, efd, err)
#pragma GCC diagnostic pop
int
fork_exec(struct socket *so, const char *ex)
{
@ -144,17 +211,18 @@ 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));
qemu_set_nonblock(so->s);
slirp_setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
slirp_set_nonblock(so->s);
so->slirp->cb->register_poll_fd(so->s, so->slirp->opaque);
return 1;
}

View file

@ -8,8 +8,11 @@
#ifndef MISC_H
#define MISC_H
#include "libslirp.h"
struct gfwd_list {
void *ex_chardev;
SlirpWriteCb write_cb;
void *opaque;
struct in_addr ex_addr; /* Server address */
int ex_fport; /* Port to telnet to */
char *ex_exec; /* Command line of what to exec */
@ -51,7 +54,15 @@ struct slirp_quehead {
void slirp_insque(void *, void *);
void slirp_remque(void *);
int add_exec(struct gfwd_list **, void *, const char *, struct in_addr, int);
int fork_exec(struct socket *so, const char *ex);
struct gfwd_list *
add_guestfwd(struct gfwd_list **ex_ptr,
SlirpWriteCb write_cb, void *opaque,
struct in_addr addr, int port);
struct gfwd_list *
add_exec(struct gfwd_list **ex_ptr, const char *cmdline,
struct in_addr addr, int port);
#endif

View file

@ -6,7 +6,6 @@
* This code is licensed under the GPL version 2 or later. See the
* COPYING file in the top-level directory.
*/
#include "qemu/osdep.h"
#include "slirp.h"
#include "ncsi-pkt.h"
@ -163,5 +162,5 @@ void ncsi_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
*pchecksum = htonl(checksum);
ncsi_rsp_len += 4;
slirp->cb->output(slirp->opaque, ncsi_reply, ETH_HLEN + ncsi_rsp_len);
slirp_send_packet_all(slirp, ncsi_reply, ETH_HLEN + ncsi_rsp_len);
}

View file

@ -3,8 +3,6 @@
* Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne.
*/
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "slirp.h"
void ndp_table_add(Slirp *slirp, struct in6_addr ip_addr,

193
slirp/qtailq.h Normal file
View file

@ -0,0 +1,193 @@
/* $NetBSD: queue.h,v 1.52 2009/04/20 09:56:08 mschuett Exp $ */
/*
* slirp version: Copy from QEMU, removed all but tail queues.
*/
/*
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)queue.h 8.5 (Berkeley) 8/20/94
*/
#ifndef QTAILQ_H
#define QTAILQ_H
/*
* A tail queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are doubly
* linked so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before or
* after an existing element, at the head of the list, or at the end of
* the list. A tail queue may be traversed in either direction.
*/
typedef struct QTailQLink {
void *tql_next;
struct QTailQLink *tql_prev;
} QTailQLink;
/*
* Tail queue definitions. The union acts as a poor man template, as if
* it were QTailQLink<type>.
*/
#define QTAILQ_HEAD(name, type) \
union name { \
struct type *tqh_first; /* first element */ \
QTailQLink tqh_circ; /* link for circular backwards list */ \
}
#define QTAILQ_HEAD_INITIALIZER(head) \
{ .tqh_circ = { NULL, &(head).tqh_circ } }
#define QTAILQ_ENTRY(type) \
union { \
struct type *tqe_next; /* next element */ \
QTailQLink tqe_circ; /* link for circular backwards list */ \
}
#define QTAILQ_INIT(head) do { \
(head)->tqh_first = NULL; \
(head)->tqh_circ.tql_prev = &(head)->tqh_circ; \
} while (/*CONSTCOND*/0)
#define QTAILQ_INSERT_HEAD(head, elm, field) do { \
if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
(head)->tqh_first->field.tqe_circ.tql_prev = \
&(elm)->field.tqe_circ; \
else \
(head)->tqh_circ.tql_prev = &(elm)->field.tqe_circ; \
(head)->tqh_first = (elm); \
(elm)->field.tqe_circ.tql_prev = &(head)->tqh_circ; \
} while (/*CONSTCOND*/0)
#define QTAILQ_INSERT_TAIL(head, elm, field) do { \
(elm)->field.tqe_next = NULL; \
(elm)->field.tqe_circ.tql_prev = (head)->tqh_circ.tql_prev; \
(head)->tqh_circ.tql_prev->tql_next = (elm); \
(head)->tqh_circ.tql_prev = &(elm)->field.tqe_circ; \
} while (/*CONSTCOND*/0)
#define QTAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
(elm)->field.tqe_next->field.tqe_circ.tql_prev = \
&(elm)->field.tqe_circ; \
else \
(head)->tqh_circ.tql_prev = &(elm)->field.tqe_circ; \
(listelm)->field.tqe_next = (elm); \
(elm)->field.tqe_circ.tql_prev = &(listelm)->field.tqe_circ; \
} while (/*CONSTCOND*/0)
#define QTAILQ_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.tqe_circ.tql_prev = (listelm)->field.tqe_circ.tql_prev; \
(elm)->field.tqe_next = (listelm); \
(listelm)->field.tqe_circ.tql_prev->tql_next = (elm); \
(listelm)->field.tqe_circ.tql_prev = &(elm)->field.tqe_circ; \
} while (/*CONSTCOND*/0)
#define QTAILQ_REMOVE(head, elm, field) do { \
if (((elm)->field.tqe_next) != NULL) \
(elm)->field.tqe_next->field.tqe_circ.tql_prev = \
(elm)->field.tqe_circ.tql_prev; \
else \
(head)->tqh_circ.tql_prev = (elm)->field.tqe_circ.tql_prev; \
(elm)->field.tqe_circ.tql_prev->tql_next = (elm)->field.tqe_next; \
(elm)->field.tqe_circ.tql_prev = NULL; \
} while (/*CONSTCOND*/0)
#define QTAILQ_FOREACH(var, head, field) \
for ((var) = ((head)->tqh_first); \
(var); \
(var) = ((var)->field.tqe_next))
#define QTAILQ_FOREACH_SAFE(var, head, field, next_var) \
for ((var) = ((head)->tqh_first); \
(var) && ((next_var) = ((var)->field.tqe_next), 1); \
(var) = (next_var))
#define QTAILQ_FOREACH_REVERSE(var, head, field) \
for ((var) = QTAILQ_LAST(head); \
(var); \
(var) = QTAILQ_PREV(var, field))
#define QTAILQ_FOREACH_REVERSE_SAFE(var, head, field, prev_var) \
for ((var) = QTAILQ_LAST(head); \
(var) && ((prev_var) = QTAILQ_PREV(var, field)); \
(var) = (prev_var))
/*
* Tail queue access methods.
*/
#define QTAILQ_EMPTY(head) ((head)->tqh_first == NULL)
#define QTAILQ_FIRST(head) ((head)->tqh_first)
#define QTAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
#define QTAILQ_IN_USE(elm, field) ((elm)->field.tqe_circ.tql_prev != NULL)
#define QTAILQ_LINK_PREV(link) \
((link).tql_prev->tql_prev->tql_next)
#define QTAILQ_LAST(head) \
((typeof((head)->tqh_first)) QTAILQ_LINK_PREV((head)->tqh_circ))
#define QTAILQ_PREV(elm, field) \
((typeof((elm)->field.tqe_next)) QTAILQ_LINK_PREV((elm)->field.tqe_circ))
#define field_at_offset(base, offset, type) \
((type *) (((char *) (base)) + (offset)))
/*
* Raw access of elements of a tail queue head. Offsets are all zero
* because it's a union.
*/
#define QTAILQ_RAW_FIRST(head) \
field_at_offset(head, 0, void *)
#define QTAILQ_RAW_TQH_CIRC(head) \
field_at_offset(head, 0, QTailQLink)
/*
* Raw access of elements of a tail entry
*/
#define QTAILQ_RAW_NEXT(elm, entry) \
field_at_offset(elm, entry, void *)
#define QTAILQ_RAW_TQE_CIRC(elm, entry) \
field_at_offset(elm, entry, QTailQLink)
/*
* Tail queue traversal using pointer arithmetic.
*/
#define QTAILQ_RAW_FOREACH(elm, head, entry) \
for ((elm) = *QTAILQ_RAW_FIRST(head); \
(elm); \
(elm) = *QTAILQ_RAW_NEXT(elm, entry))
/*
* Tail queue insertion using pointer arithmetic.
*/
#define QTAILQ_RAW_INSERT_TAIL(head, elm, entry) do { \
*QTAILQ_RAW_NEXT(elm, entry) = NULL; \
QTAILQ_RAW_TQE_CIRC(elm, entry)->tql_prev = QTAILQ_RAW_TQH_CIRC(head)->tql_prev; \
QTAILQ_RAW_TQH_CIRC(head)->tql_prev->tql_next = (elm); \
QTAILQ_RAW_TQH_CIRC(head)->tql_prev = QTAILQ_RAW_TQE_CIRC(elm, entry); \
} while (/*CONSTCOND*/0)
#endif /* QTAILQ_H */

View file

@ -5,9 +5,7 @@
* terms and conditions of the copyright.
*/
#include "qemu/osdep.h"
#include "slirp.h"
#include "qemu/main-loop.h"
static void sbappendsb(struct sbuf *sb, struct mbuf *m);
@ -17,7 +15,7 @@ sbfree(struct sbuf *sb)
free(sb->sb_data);
}
void
bool
sbdrop(struct sbuf *sb, int num)
{
int limit = sb->sb_datalen / 2;
@ -34,8 +32,10 @@ sbdrop(struct sbuf *sb, int num)
sb->sb_rptr -= sb->sb_datalen;
if (sb->sb_cc < limit && sb->sb_cc + num >= limit) {
qemu_notify_event();
return true;
}
return false;
}
void

View file

@ -21,7 +21,7 @@ struct sbuf {
};
void sbfree(struct sbuf *);
void sbdrop(struct sbuf *, int);
bool sbdrop(struct sbuf *, int);
void sbreserve(struct sbuf *, int);
void sbappend(struct socket *, struct mbuf *);
void sbcopy(struct sbuf *, int, int, char *);

File diff suppressed because it is too large Load diff

View file

@ -3,10 +3,17 @@
#ifdef _WIN32
typedef char *caddr_t;
/* as defined in sdkddkver.h */
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0600 /* Vista */
#endif
/* reduces the number of implicitly included headers */
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
# include <windows.h>
# include <winsock2.h>
# include <windows.h>
# include <ws2tcpip.h>
# include <sys/timeb.h>
# include <iphlpapi.h>
@ -19,19 +26,10 @@ typedef char *caddr_t;
#ifndef _WIN32
#include <sys/uio.h>
#endif
#ifndef _WIN32
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
#ifndef _WIN32
#include <sys/socket.h>
#endif
#ifndef _WIN32
# include <sys/ioctl.h>
#include <sys/ioctl.h>
#endif
#ifdef __APPLE__
@ -45,10 +43,8 @@ typedef char *caddr_t;
#define quehead slirp_quehead
#include "debug.h"
#include "qemu/queue.h"
#include "qemu/sockets.h"
#include "net/eth.h"
#include "util.h"
#include "qtailq.h"
#include "libslirp.h"
#include "ip.h"
@ -93,7 +89,7 @@ struct slirp_arphdr {
uint32_t ar_sip; /* sender IP address */
unsigned char ar_tha[ETH_ALEN]; /* target hardware address */
uint32_t ar_tip; /* target IP address */
} QEMU_PACKED;
} SLIRP_PACKED;
#define ARP_TABLE_SIZE 16
@ -110,7 +106,7 @@ bool arp_table_search(Slirp *slirp, uint32_t ip_addr,
struct ndpentry {
unsigned char eth_addr[ETH_ALEN]; /* sender hardware address */
struct in6_addr ip_addr; /* sender IP address */
} QEMU_PACKED;
} SLIRP_PACKED;
#define NDP_TABLE_SIZE 16
@ -126,8 +122,8 @@ bool ndp_table_search(Slirp *slirp, struct in6_addr ip_addr,
struct Slirp {
QTAILQ_ENTRY(Slirp) entry;
u_int time_fasttimo;
u_int last_slowtimo;
unsigned time_fasttimo;
unsigned last_slowtimo;
bool do_slowtimo;
bool in_enabled, in6_enabled;
@ -193,7 +189,7 @@ struct Slirp {
NdpTable ndp_table;
GRand *grand;
QEMUTimer *ra_timer;
void *ra_timer;
const SlirpCb *cb;
void *opaque;
@ -247,7 +243,7 @@ int ip6_output(struct socket *, struct mbuf *, int fast);
/* tcp_input.c */
void tcp_input(register struct mbuf *, int, struct socket *, unsigned short af);
int tcp_mss(register struct tcpcb *, u_int);
int tcp_mss(register struct tcpcb *, unsigned);
/* tcp_output.c */
int tcp_output(register struct tcpcb *);
@ -270,4 +266,9 @@ int tcp_emu(struct socket *, struct mbuf *);
int tcp_ctl(struct socket *);
struct tcpcb *tcp_drop(struct tcpcb *tp, int err);
struct socket *
slirp_find_ctl_socket(Slirp *slirp, struct in_addr guest_addr, int guest_port);
void slirp_send_packet_all(Slirp *slirp, const void *buf, size_t len);
#endif

View file

@ -5,8 +5,6 @@
* terms and conditions of the copyright.
*/
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "slirp.h"
#include "ip_icmp.h"
#ifdef __sun__
@ -187,7 +185,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 +201,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 +231,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;
}
@ -508,7 +506,7 @@ sorecvfrom(struct socket *so)
/* XXX Check if reply is "correct"? */
if(len == -1 || len == 0) {
u_char code=ICMP_UNREACH_PORT;
uint8_t code=ICMP_UNREACH_PORT;
if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
@ -554,7 +552,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;
@ -678,8 +676,8 @@ sosendto(struct socket *so, struct mbuf *m)
* Listen for incoming TCP connections
*/
struct socket *
tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
u_int lport, int flags)
tcp_listen(Slirp *slirp, uint32_t haddr, unsigned hport, uint32_t laddr,
unsigned lport, int flags)
{
struct sockaddr_in addr;
struct socket *so;
@ -719,14 +717,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 +735,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;
@ -928,3 +926,10 @@ void sotranslate_accept(struct socket *so)
break;
}
}
void sodrop(struct socket *s, int num)
{
if (sbdrop(&s->so_snd, num)) {
s->slirp->cb->notify(s->slirp->opaque);
}
}

View file

@ -8,6 +8,8 @@
#ifndef SLIRP_SOCKET_H
#define SLIRP_SOCKET_H
#include "misc.h"
#define SO_EXPIRE 240000
#define SO_EXPIREFAST 10000
@ -25,6 +27,7 @@ struct socket {
struct socket *so_next,*so_prev; /* For a linked list of sockets */
int s; /* The actual socket */
struct gfwd_list *guestfwd;
int pollfds_idx; /* GPollFD GArray index */
@ -58,7 +61,7 @@ struct socket {
int32_t so_state; /* internal state flags SS_*, below */
struct tcpcb *so_tcpcb; /* pointer to TCP protocol control block */
u_int so_expire; /* When the socket will expire */
unsigned so_expire; /* When the socket will expire */
int so_queued; /* Number of packets queued from this socket */
int so_nqueued; /* Number of packets queued in a row
@ -67,7 +70,6 @@ struct socket {
struct sbuf so_rcv; /* Receive buffer */
struct sbuf so_snd; /* Send buffer */
void * chardev;
};
@ -142,7 +144,7 @@ int sosendoob(struct socket *);
int sowrite(struct socket *);
void sorecvfrom(struct socket *);
int sosendto(struct socket *, struct mbuf *);
struct socket * tcp_listen(Slirp *, uint32_t, u_int, uint32_t, u_int,
struct socket * tcp_listen(Slirp *, uint32_t, unsigned, uint32_t, unsigned,
int);
void soisfconnecting(register struct socket *);
void soisfconnected(register struct socket *);
@ -154,6 +156,7 @@ int soreadbuf(struct socket *so, const char *buf, int size);
void sotranslate_out(struct socket *, struct sockaddr_storage *);
void sotranslate_in(struct socket *, struct sockaddr_storage *);
void sotranslate_accept(struct socket *);
void sodrop(struct socket *, int num);
#endif /* SLIRP_SOCKET_H */

394
slirp/state.c Normal file
View file

@ -0,0 +1,394 @@
/*
* libslirp
*
* Copyright (c) 2004-2008 Fabrice Bellard
*
* 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 "qemu/osdep.h"
#include "slirp.h"
#include "state.h"
#include "migration/vmstate.h"
#include "migration/qemu-file-types.h"
#include "migration/register.h"
static int slirp_tcp_post_load(void *opaque, int version)
{
tcp_template((struct tcpcb *)opaque);
return 0;
}
static const VMStateDescription vmstate_slirp_tcp = {
.name = "slirp-tcp",
.version_id = 0,
.post_load = slirp_tcp_post_load,
.fields = (VMStateField[]) {
VMSTATE_INT16(t_state, struct tcpcb),
VMSTATE_INT16_ARRAY(t_timer, struct tcpcb, TCPT_NTIMERS),
VMSTATE_INT16(t_rxtshift, struct tcpcb),
VMSTATE_INT16(t_rxtcur, struct tcpcb),
VMSTATE_INT16(t_dupacks, struct tcpcb),
VMSTATE_UINT16(t_maxseg, struct tcpcb),
VMSTATE_UINT8(t_force, struct tcpcb),
VMSTATE_UINT16(t_flags, struct tcpcb),
VMSTATE_UINT32(snd_una, struct tcpcb),
VMSTATE_UINT32(snd_nxt, struct tcpcb),
VMSTATE_UINT32(snd_up, struct tcpcb),
VMSTATE_UINT32(snd_wl1, struct tcpcb),
VMSTATE_UINT32(snd_wl2, struct tcpcb),
VMSTATE_UINT32(iss, struct tcpcb),
VMSTATE_UINT32(snd_wnd, struct tcpcb),
VMSTATE_UINT32(rcv_wnd, struct tcpcb),
VMSTATE_UINT32(rcv_nxt, struct tcpcb),
VMSTATE_UINT32(rcv_up, struct tcpcb),
VMSTATE_UINT32(irs, struct tcpcb),
VMSTATE_UINT32(rcv_adv, struct tcpcb),
VMSTATE_UINT32(snd_max, struct tcpcb),
VMSTATE_UINT32(snd_cwnd, struct tcpcb),
VMSTATE_UINT32(snd_ssthresh, struct tcpcb),
VMSTATE_INT16(t_idle, struct tcpcb),
VMSTATE_INT16(t_rtt, struct tcpcb),
VMSTATE_UINT32(t_rtseq, struct tcpcb),
VMSTATE_INT16(t_srtt, struct tcpcb),
VMSTATE_INT16(t_rttvar, struct tcpcb),
VMSTATE_UINT16(t_rttmin, struct tcpcb),
VMSTATE_UINT32(max_sndwnd, struct tcpcb),
VMSTATE_UINT8(t_oobflags, struct tcpcb),
VMSTATE_UINT8(t_iobc, struct tcpcb),
VMSTATE_INT16(t_softerror, struct tcpcb),
VMSTATE_UINT8(snd_scale, struct tcpcb),
VMSTATE_UINT8(rcv_scale, struct tcpcb),
VMSTATE_UINT8(request_r_scale, struct tcpcb),
VMSTATE_UINT8(requested_s_scale, struct tcpcb),
VMSTATE_UINT32(ts_recent, struct tcpcb),
VMSTATE_UINT32(ts_recent_age, struct tcpcb),
VMSTATE_UINT32(last_ack_sent, struct tcpcb),
VMSTATE_END_OF_LIST()
}
};
/* The sbuf has a pair of pointers that are migrated as offsets;
* we calculate the offsets and restore the pointers using
* pre_save/post_load on a tmp structure.
*/
struct sbuf_tmp {
struct sbuf *parent;
uint32_t roff, woff;
};
static int sbuf_tmp_pre_save(void *opaque)
{
struct sbuf_tmp *tmp = opaque;
tmp->woff = tmp->parent->sb_wptr - tmp->parent->sb_data;
tmp->roff = tmp->parent->sb_rptr - tmp->parent->sb_data;
return 0;
}
static int sbuf_tmp_post_load(void *opaque, int version)
{
struct sbuf_tmp *tmp = opaque;
uint32_t requested_len = tmp->parent->sb_datalen;
/* Allocate the buffer space used by the field after the tmp */
sbreserve(tmp->parent, tmp->parent->sb_datalen);
if (tmp->parent->sb_datalen != requested_len) {
return -ENOMEM;
}
if (tmp->woff >= requested_len ||
tmp->roff >= requested_len) {
g_critical("invalid sbuf offsets r/w=%u/%u len=%u",
tmp->roff, tmp->woff, requested_len);
return -EINVAL;
}
tmp->parent->sb_wptr = tmp->parent->sb_data + tmp->woff;
tmp->parent->sb_rptr = tmp->parent->sb_data + tmp->roff;
return 0;
}
static const VMStateDescription vmstate_slirp_sbuf_tmp = {
.name = "slirp-sbuf-tmp",
.post_load = sbuf_tmp_post_load,
.pre_save = sbuf_tmp_pre_save,
.version_id = 0,
.fields = (VMStateField[]) {
VMSTATE_UINT32(woff, struct sbuf_tmp),
VMSTATE_UINT32(roff, struct sbuf_tmp),
VMSTATE_END_OF_LIST()
}
};
static const VMStateDescription vmstate_slirp_sbuf = {
.name = "slirp-sbuf",
.version_id = 0,
.fields = (VMStateField[]) {
VMSTATE_UINT32(sb_cc, struct sbuf),
VMSTATE_UINT32(sb_datalen, struct sbuf),
VMSTATE_WITH_TMP(struct sbuf, struct sbuf_tmp, vmstate_slirp_sbuf_tmp),
VMSTATE_VBUFFER_UINT32(sb_data, struct sbuf, 0, NULL, sb_datalen),
VMSTATE_END_OF_LIST()
}
};
static bool slirp_older_than_v4(void *opaque, int version_id)
{
return version_id < 4;
}
static bool slirp_family_inet(void *opaque, int version_id)
{
union slirp_sockaddr *ssa = (union slirp_sockaddr *)opaque;
return ssa->ss.ss_family == AF_INET;
}
static int slirp_socket_pre_load(void *opaque)
{
struct socket *so = opaque;
if (tcp_attach(so) < 0) {
return -ENOMEM;
}
/* Older versions don't load these fields */
so->so_ffamily = AF_INET;
so->so_lfamily = AF_INET;
return 0;
}
#ifndef _WIN32
#define VMSTATE_SIN4_ADDR(f, s, t) VMSTATE_UINT32_TEST(f, s, t)
#else
/* Win uses u_long rather than uint32_t - but it's still 32bits long */
#define VMSTATE_SIN4_ADDR(f, s, t) VMSTATE_SINGLE_TEST(f, s, t, 0, \
vmstate_info_uint32, u_long)
#endif
/* The OS provided ss_family field isn't that portable; it's size
* and type varies (16/8 bit, signed, unsigned)
* and the values it contains aren't fully portable.
*/
typedef struct SS_FamilyTmpStruct {
union slirp_sockaddr *parent;
uint16_t portable_family;
} SS_FamilyTmpStruct;
#define SS_FAMILY_MIG_IPV4 2 /* Linux, BSD, Win... */
#define SS_FAMILY_MIG_IPV6 10 /* Linux */
#define SS_FAMILY_MIG_OTHER 0xffff
static int ss_family_pre_save(void *opaque)
{
SS_FamilyTmpStruct *tss = opaque;
tss->portable_family = SS_FAMILY_MIG_OTHER;
if (tss->parent->ss.ss_family == AF_INET) {
tss->portable_family = SS_FAMILY_MIG_IPV4;
} else if (tss->parent->ss.ss_family == AF_INET6) {
tss->portable_family = SS_FAMILY_MIG_IPV6;
}
return 0;
}
static int ss_family_post_load(void *opaque, int version_id)
{
SS_FamilyTmpStruct *tss = opaque;
switch (tss->portable_family) {
case SS_FAMILY_MIG_IPV4:
tss->parent->ss.ss_family = AF_INET;
break;
case SS_FAMILY_MIG_IPV6:
case 23: /* compatibility: AF_INET6 from mingw */
case 28: /* compatibility: AF_INET6 from FreeBSD sys/socket.h */
tss->parent->ss.ss_family = AF_INET6;
break;
default:
g_critical("invalid ss_family type %x", tss->portable_family);
return -EINVAL;
}
return 0;
}
static const VMStateDescription vmstate_slirp_ss_family = {
.name = "slirp-socket-addr/ss_family",
.pre_save = ss_family_pre_save,
.post_load = ss_family_post_load,
.fields = (VMStateField[]) {
VMSTATE_UINT16(portable_family, SS_FamilyTmpStruct),
VMSTATE_END_OF_LIST()
}
};
static const VMStateDescription vmstate_slirp_socket_addr = {
.name = "slirp-socket-addr",
.version_id = 4,
.fields = (VMStateField[]) {
VMSTATE_WITH_TMP(union slirp_sockaddr, SS_FamilyTmpStruct,
vmstate_slirp_ss_family),
VMSTATE_SIN4_ADDR(sin.sin_addr.s_addr, union slirp_sockaddr,
slirp_family_inet),
VMSTATE_UINT16_TEST(sin.sin_port, union slirp_sockaddr,
slirp_family_inet),
#if 0
/* Untested: Needs checking by someone with IPv6 test */
VMSTATE_BUFFER_TEST(sin6.sin6_addr, union slirp_sockaddr,
slirp_family_inet6),
VMSTATE_UINT16_TEST(sin6.sin6_port, union slirp_sockaddr,
slirp_family_inet6),
VMSTATE_UINT32_TEST(sin6.sin6_flowinfo, union slirp_sockaddr,
slirp_family_inet6),
VMSTATE_UINT32_TEST(sin6.sin6_scope_id, union slirp_sockaddr,
slirp_family_inet6),
#endif
VMSTATE_END_OF_LIST()
}
};
static const VMStateDescription vmstate_slirp_socket = {
.name = "slirp-socket",
.version_id = 4,
.pre_load = slirp_socket_pre_load,
.fields = (VMStateField[]) {
VMSTATE_UINT32(so_urgc, struct socket),
/* Pre-v4 versions */
VMSTATE_SIN4_ADDR(so_faddr.s_addr, struct socket,
slirp_older_than_v4),
VMSTATE_SIN4_ADDR(so_laddr.s_addr, struct socket,
slirp_older_than_v4),
VMSTATE_UINT16_TEST(so_fport, struct socket, slirp_older_than_v4),
VMSTATE_UINT16_TEST(so_lport, struct socket, slirp_older_than_v4),
/* v4 and newer */
VMSTATE_STRUCT(fhost, struct socket, 4, vmstate_slirp_socket_addr,
union slirp_sockaddr),
VMSTATE_STRUCT(lhost, struct socket, 4, vmstate_slirp_socket_addr,
union slirp_sockaddr),
VMSTATE_UINT8(so_iptos, struct socket),
VMSTATE_UINT8(so_emu, struct socket),
VMSTATE_UINT8(so_type, struct socket),
VMSTATE_INT32(so_state, struct socket),
VMSTATE_STRUCT(so_rcv, struct socket, 0, vmstate_slirp_sbuf,
struct sbuf),
VMSTATE_STRUCT(so_snd, struct socket, 0, vmstate_slirp_sbuf,
struct sbuf),
VMSTATE_STRUCT_POINTER(so_tcpcb, struct socket, vmstate_slirp_tcp,
struct tcpcb),
VMSTATE_END_OF_LIST()
}
};
static const VMStateDescription vmstate_slirp_bootp_client = {
.name = "slirp_bootpclient",
.fields = (VMStateField[]) {
VMSTATE_UINT16(allocated, BOOTPClient),
VMSTATE_BUFFER(macaddr, BOOTPClient),
VMSTATE_END_OF_LIST()
}
};
static const VMStateDescription vmstate_slirp = {
.name = "slirp",
.version_id = 4,
.fields = (VMStateField[]) {
VMSTATE_UINT16_V(ip_id, Slirp, 2),
VMSTATE_STRUCT_ARRAY(bootp_clients, Slirp, NB_BOOTP_CLIENTS, 3,
vmstate_slirp_bootp_client, BOOTPClient),
VMSTATE_END_OF_LIST()
}
};
static void slirp_state_save(QEMUFile *f, void *opaque)
{
Slirp *slirp = opaque;
struct gfwd_list *ex_ptr;
for (ex_ptr = slirp->guestfwd_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
if (ex_ptr->write_cb) {
struct socket *so;
so = slirp_find_ctl_socket(slirp, ex_ptr->ex_addr,
ntohs(ex_ptr->ex_fport));
if (!so) {
continue;
}
qemu_put_byte(f, 42);
vmstate_save_state(f, &vmstate_slirp_socket, so, NULL);
}
qemu_put_byte(f, 0);
vmstate_save_state(f, &vmstate_slirp, slirp, NULL);
}
static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
{
Slirp *slirp = opaque;
struct gfwd_list *ex_ptr;
while (qemu_get_byte(f)) {
int ret;
struct socket *so = socreate(slirp);
ret = vmstate_load_state(f, &vmstate_slirp_socket, so, version_id);
if (ret < 0) {
return ret;
}
if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) !=
slirp->vnetwork_addr.s_addr) {
return -EINVAL;
}
for (ex_ptr = slirp->guestfwd_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
if (ex_ptr->write_cb &&
so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr &&
so->so_fport == ex_ptr->ex_fport) {
break;
}
}
if (!ex_ptr) {
return -EINVAL;
}
}
return vmstate_load_state(f, &vmstate_slirp, slirp, version_id);
}
void slirp_state_register(Slirp *slirp)
{
static SaveVMHandlers savevm_slirp_state = {
.save_state = slirp_state_save,
.load_state = slirp_state_load,
};
register_savevm_live(NULL, "slirp", 0, 4, &savevm_slirp_state, slirp);
}
void slirp_state_unregister(Slirp *slirp)
{
unregister_savevm(NULL, "slirp", slirp);
}

9
slirp/state.h Normal file
View file

@ -0,0 +1,9 @@
#ifndef SLIRP_STATE_H_
#define SLIRP_STATE_H_
#include "libslirp.h"
void slirp_state_register(Slirp *slirp);
void slirp_state_unregister(Slirp *slirp);
#endif /* SLIRP_STATE_H_ */

View file

@ -38,7 +38,6 @@
* terms and conditions of the copyright.
*/
#include "qemu/osdep.h"
#include "slirp.h"
#include "ip_icmp.h"
@ -77,7 +76,7 @@
} \
}
static void tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt,
static void tcp_dooptions(struct tcpcb *tp, uint8_t *cp, int cnt,
struct tcpiphdr *ti);
static void tcp_xmit_timer(register struct tcpcb *tp, int rtt);
@ -198,7 +197,7 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso, unsigned short af)
struct ip save_ip, *ip;
struct ip6 save_ip6, *ip6;
register struct tcpiphdr *ti;
caddr_t optp = NULL;
char *optp = NULL;
int optlen = 0;
int len, tlen, off;
register struct tcpcb *tp = NULL;
@ -206,7 +205,7 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso, unsigned short af)
struct socket *so = NULL;
int todrop, acked, ourfinisacked, needoutput = 0;
int iss = 0;
u_long tiwin;
uint32_t tiwin;
int ret;
struct sockaddr_storage lhost, fhost;
struct sockaddr_in *lhost4, *fhost4;
@ -328,7 +327,7 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso, unsigned short af)
ti->ti_len = tlen;
if (off > sizeof (struct tcphdr)) {
optlen = off - sizeof (struct tcphdr);
optp = mtod(m, caddr_t) + sizeof (struct tcpiphdr);
optp = mtod(m, char *) + sizeof (struct tcpiphdr);
}
tiflags = ti->ti_flags;
@ -470,7 +469,7 @@ findso:
* else do it below (after getting remote address).
*/
if (optp && tp->t_state != TCPS_LISTEN)
tcp_dooptions(tp, (u_char *)optp, optlen, ti);
tcp_dooptions(tp, (uint8_t *)optp, optlen, ti);
/*
* Header prediction: check for the two common cases
@ -506,7 +505,7 @@ findso:
SEQ_GT(ti->ti_ack, tp->t_rtseq))
tcp_xmit_timer(tp, tp->t_rtt);
acked = ti->ti_ack - tp->snd_una;
sbdrop(&so->so_snd, acked);
sodrop(so, acked);
tp->snd_una = ti->ti_ack;
m_free(m);
@ -725,7 +724,7 @@ findso:
tcp_template(tp);
if (optp)
tcp_dooptions(tp, (u_char *)optp, optlen, ti);
tcp_dooptions(tp, (uint8_t *)optp, optlen, ti);
if (iss)
tp->iss = iss;
@ -1040,7 +1039,7 @@ trimthenstep6:
tp->t_dupacks = 0;
else if (++tp->t_dupacks == TCPREXMTTHRESH) {
tcp_seq onxt = tp->snd_nxt;
u_int win =
unsigned win =
MIN(tp->snd_wnd, tp->snd_cwnd) /
2 / tp->t_maxseg;
@ -1109,8 +1108,8 @@ trimthenstep6:
* (maxseg^2 / cwnd per packet).
*/
{
register u_int cw = tp->snd_cwnd;
register u_int incr = tp->t_maxseg;
register unsigned cw = tp->snd_cwnd;
register unsigned incr = tp->t_maxseg;
if (cw > tp->snd_ssthresh)
incr = incr * incr / cw;
@ -1118,10 +1117,10 @@ trimthenstep6:
}
if (acked > so->so_snd.sb_cc) {
tp->snd_wnd -= so->so_snd.sb_cc;
sbdrop(&so->so_snd, (int )so->so_snd.sb_cc);
sodrop(so, (int)so->so_snd.sb_cc);
ourfinisacked = 1;
} else {
sbdrop(&so->so_snd, acked);
sodrop(so, acked);
tp->snd_wnd -= acked;
ourfinisacked = 0;
}
@ -1382,7 +1381,7 @@ drop:
}
static void
tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt, struct tcpiphdr *ti)
tcp_dooptions(struct tcpcb *tp, uint8_t *cp, int cnt, struct tcpiphdr *ti)
{
uint16_t mss;
int opt, optlen;
@ -1512,7 +1511,7 @@ tcp_xmit_timer(register struct tcpcb *tp, int rtt)
*/
int
tcp_mss(struct tcpcb *tp, u_int offer)
tcp_mss(struct tcpcb *tp, unsigned offer)
{
struct socket *so = tp->t_socket;
int mss;

View file

@ -38,10 +38,9 @@
* terms and conditions of the copyright.
*/
#include "qemu/osdep.h"
#include "slirp.h"
static const u_char tcp_outflags[TCP_NSTATES] = {
static const uint8_t tcp_outflags[TCP_NSTATES] = {
TH_RST|TH_ACK, 0, TH_SYN, TH_SYN|TH_ACK,
TH_ACK, TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK,
TH_FIN|TH_ACK, TH_ACK, TH_ACK,
@ -64,7 +63,7 @@ tcp_output(struct tcpcb *tp)
register struct tcpiphdr *ti, tcpiph_save;
struct ip *ip;
struct ip6 *ip6;
u_char opt[MAX_TCPOPTLEN];
uint8_t opt[MAX_TCPOPTLEN];
unsigned optlen, hdrlen;
int idle, sendalot;
@ -272,7 +271,7 @@ send:
opt[0] = TCPOPT_MAXSEG;
opt[1] = 4;
mss = htons((uint16_t) tcp_mss(tp, 0));
memcpy((caddr_t)(opt + 2), (caddr_t)&mss, sizeof(mss));
memcpy((char *)(opt + 2), (char *)&mss, sizeof(mss));
optlen = 4;
}
}
@ -302,7 +301,7 @@ send:
m->m_data += IF_MAXLINKHDR;
m->m_len = hdrlen;
sbcopy(&so->so_snd, off, (int) len, mtod(m, caddr_t) + hdrlen);
sbcopy(&so->so_snd, off, (int) len, mtod(m, char *) + hdrlen);
m->m_len += len;
/*
@ -325,7 +324,7 @@ send:
ti = mtod(m, struct tcpiphdr *);
memcpy((caddr_t)ti, &tp->t_template, sizeof (struct tcpiphdr));
memcpy((char *)ti, &tp->t_template, sizeof (struct tcpiphdr));
/*
* Fill in fields, remembering maximum advertised
@ -354,7 +353,7 @@ send:
ti->ti_seq = htonl(tp->snd_max);
ti->ti_ack = htonl(tp->rcv_nxt);
if (optlen) {
memcpy((caddr_t)(ti + 1), (caddr_t)opt, optlen);
memcpy((char *)(ti + 1), (char *)opt, optlen);
ti->ti_off = (sizeof (struct tcphdr) + optlen) >> 2;
}
ti->ti_flags = flags;

View file

@ -38,7 +38,6 @@
* terms and conditions of the copyright.
*/
#include "qemu/osdep.h"
#include "slirp.h"
/* patchable/settable parameters for tcp */
@ -164,7 +163,7 @@ tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m,
* ti points into m so the next line is just making
* the mbuf point to ti
*/
m->m_data = (caddr_t)ti;
m->m_data = (char *)ti;
m->m_len = sizeof (struct tcpiphdr);
tlen = 0;
@ -183,7 +182,7 @@ tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m,
}
#undef xchg
}
ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + tlen));
ti->ti_len = htons((uint16_t)(sizeof (struct tcphdr) + tlen));
tlen += sizeof (struct tcpiphdr);
m->m_len = tlen;
@ -337,7 +336,8 @@ 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);
so->slirp->cb->unregister_poll_fd(so->s, so->slirp->opaque);
slirp_closesocket(so->s);
sbfree(&so->so_rcv);
sbfree(&so->so_snd);
sofree(so);
@ -407,17 +407,18 @@ 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_set_nonblock(s);
so->slirp->cb->register_poll_fd(so->s, so->slirp->opaque);
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");
@ -484,11 +485,12 @@ void tcp_connect(struct socket *inso)
tcp_close(sototcpcb(so)); /* This will sofree() as well */
return;
}
qemu_set_nonblock(s);
socket_set_fast_reuse(s);
slirp_set_nonblock(s);
so->slirp->cb->register_poll_fd(so->s, so->slirp->opaque);
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 +498,8 @@ 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);
so->slirp->cb->unregister_poll_fd(so->s, so->slirp->opaque);
slirp_closesocket(so->s);
/* Don't select it yet, even though we have an FD */
/* if it's not FACCEPTONCE, it's already NOFDREF */
@ -610,10 +613,10 @@ int
tcp_emu(struct socket *so, struct mbuf *m)
{
Slirp *slirp = so->slirp;
u_int n1, n2, n3, n4, n5, n6;
unsigned n1, n2, n3, n4, n5, n6;
char buff[257];
uint32_t laddr;
u_int lport;
unsigned lport;
char *bptr;
DEBUG_CALL("tcp_emu");
@ -850,7 +853,7 @@ tcp_emu(struct socket *so, struct mbuf *m)
bptr = m->m_data;
while (bptr < m->m_data + m->m_len) {
u_short p;
uint16_t p;
static int ra = 0;
char ra_tbl[4];
@ -906,8 +909,8 @@ tcp_emu(struct socket *so, struct mbuf *m)
/* This is the field containing the port
* number that RA-player is listening to.
*/
lport = (((u_char*)bptr)[0] << 8)
+ ((u_char *)bptr)[1];
lport = (((uint8_t*)bptr)[0] << 8)
+ ((uint8_t *)bptr)[1];
if (lport < 6970)
lport += 256; /* don't know why */
if (lport < 6970 || lport > 7170)
@ -925,8 +928,8 @@ tcp_emu(struct socket *so, struct mbuf *m)
}
if (p == 7071)
p = 0;
*(u_char *)bptr++ = (p >> 8) & 0xff;
*(u_char *)bptr = p & 0xff;
*(uint8_t *)bptr++ = (p >> 8) & 0xff;
*(uint8_t *)bptr = p & 0xff;
ra = 0;
return 1; /* port redirected, we're done */
break;
@ -964,9 +967,9 @@ int tcp_ctl(struct socket *so)
for (ex_ptr = slirp->guestfwd_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
if (ex_ptr->ex_fport == so->so_fport &&
so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) {
if (ex_ptr->ex_chardev) {
if (ex_ptr->write_cb) {
so->s = -1;
so->chardev = ex_ptr->ex_chardev;
so->guestfwd = ex_ptr;
return 1;
}
DEBUG_MISC(" executing %s", ex_ptr->ex_exec);

View file

@ -30,7 +30,6 @@
* tcp_timer.c,v 1.2 1994/08/02 07:49:10 davidg Exp
*/
#include "qemu/osdep.h"
#include "slirp.h"
static struct tcpcb *tcp_timers(register struct tcpcb *tp, int timer);
@ -233,7 +232,7 @@ tcp_timers(register struct tcpcb *tp, int timer)
* to go below this.)
*/
{
u_int win = MIN(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg;
unsigned win = MIN(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg;
if (win < 2)
win = 2;
tp->snd_cwnd = tp->t_maxseg;

View file

@ -47,9 +47,9 @@ struct tcpcb {
short t_rxtshift; /* log(2) of rexmt exp. backoff */
short t_rxtcur; /* current retransmit value */
short t_dupacks; /* consecutive dup acks recd */
u_short t_maxseg; /* maximum segment size */
uint16_t t_maxseg; /* maximum segment size */
uint8_t t_force; /* 1 if forcing out a byte */
u_short t_flags;
uint16_t t_flags;
#define TF_ACKNOW 0x0001 /* ack peer immediately */
#define TF_DELACK 0x0002 /* ack, but try to delay it */
#define TF_NODELAY 0x0004 /* don't delay packets to coalesce */
@ -105,7 +105,7 @@ struct tcpcb {
tcp_seq t_rtseq; /* sequence number being timed */
short t_srtt; /* smoothed round-trip time */
short t_rttvar; /* variance in round-trip time */
u_short t_rttmin; /* minimum rtt allowed */
uint16_t t_rttmin; /* minimum rtt allowed */
uint32_t max_sndwnd; /* largest window peer has offered */
/* out-of-band data */
@ -116,10 +116,10 @@ struct tcpcb {
short t_softerror; /* possible error not yet reported */
/* RFC 1323 variables */
u_char snd_scale; /* window scaling for send window */
u_char rcv_scale; /* window scaling for recv window */
u_char request_r_scale; /* pending window scaling */
u_char requested_s_scale;
uint8_t snd_scale; /* window scaling for send window */
uint8_t rcv_scale; /* window scaling for recv window */
uint8_t request_r_scale; /* pending window scaling */
uint8_t requested_s_scale;
uint32_t ts_recent; /* timestamp echo data */
uint32_t ts_recent_age; /* when last updated */
tcp_seq last_ack_sent;

View file

@ -22,11 +22,11 @@
* THE SOFTWARE.
*/
#include "qemu/osdep.h"
#include "slirp.h"
#include "qemu-common.h"
#include "qemu/cutils.h"
#include "trace.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
static inline int tftp_session_in_use(struct tftp_session *spt)
{
@ -205,7 +205,8 @@ static void tftp_send_error(struct tftp_session *spt,
struct mbuf *m;
struct tftp_t *tp;
trace_slirp_tftp_error(msg);
DEBUG_TFTP("tftp error msg: %s", msg);
m = m_get(spt->slirp);
if (!m) {
@ -216,7 +217,7 @@ static void tftp_send_error(struct tftp_session *spt,
tp->tp_op = htons(TFTP_ERROR);
tp->x.tp_error.tp_error_code = htons(errorcode);
pstrcpy((char *)tp->x.tp_error.tp_msg, sizeof(tp->x.tp_error.tp_msg), msg);
slirp_pstrcpy((char *)tp->x.tp_error.tp_msg, sizeof(tp->x.tp_error.tp_msg), msg);
m->m_len = sizeof(struct tftp_t) - (TFTP_BLOCKSIZE_MAX + 2) + 3 + strlen(msg)
- sizeof(struct udphdr);
@ -325,7 +326,8 @@ static void tftp_handle_rrq(Slirp *slirp, struct sockaddr_storage *srcsas,
break;
}
}
trace_slirp_tftp_rrq(req_fname);
DEBUG_TFTP("tftp rrq file: %s", req_fname);
/* check mode */
if ((pktlen - k) < 6) {

View file

@ -1,5 +0,0 @@
# See docs/devel/tracing.txt for syntax documentation.
# slirp/tftp.c
slirp_tftp_rrq(const char *file) "file: %s"
slirp_tftp_error(const char *file) "msg: %s"

View file

@ -38,7 +38,6 @@
* terms and conditions of the copyright.
*/
#include "qemu/osdep.h"
#include "slirp.h"
#include "ip_icmp.h"
@ -93,7 +92,7 @@ udp_input(register struct mbuf *m, int iphlen)
* Get IP and UDP header together in first mbuf.
*/
ip = mtod(m, struct ip *);
uh = (struct udphdr *)((caddr_t)ip + iphlen);
uh = (struct udphdr *)((char *)ip + iphlen);
/*
* Make mbuf data length reflect UDP length.
@ -281,7 +280,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 +291,8 @@ udp_attach(struct socket *so, unsigned short af)
void
udp_detach(struct socket *so)
{
closesocket(so->s);
so->slirp->cb->unregister_poll_fd(so->s, so->slirp->opaque);
slirp_closesocket(so->s);
sofree(so);
}
@ -319,15 +319,15 @@ udp_tos(struct socket *so)
}
struct socket *
udp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
u_int lport, int flags)
udp_listen(Slirp *slirp, uint32_t haddr, unsigned hport, uint32_t laddr,
unsigned lport, int flags)
{
struct sockaddr_in addr;
struct socket *so;
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;

View file

@ -78,7 +78,7 @@ void udp_cleanup(Slirp *);
void udp_input(register struct mbuf *, int);
int udp_attach(struct socket *, unsigned short af);
void udp_detach(struct socket *);
struct socket * udp_listen(Slirp *, uint32_t, u_int, uint32_t, u_int,
struct socket * udp_listen(Slirp *, uint32_t, unsigned, uint32_t, unsigned,
int);
int udp_output(struct socket *so, struct mbuf *m,
struct sockaddr_in *saddr, struct sockaddr_in *daddr,

View file

@ -3,8 +3,6 @@
* Guillaume Subiron
*/
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "slirp.h"
#include "udp.h"
#include "dhcpv6.h"

207
slirp/util.c Normal file
View file

@ -0,0 +1,207 @@
/*
* 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
void slirp_set_nonblock(int fd)
{
#ifndef _WIN32
int f;
f = fcntl(fd, F_GETFL);
assert(f != -1);
f = fcntl(fd, F_SETFL, f | O_NONBLOCK);
assert(f != -1);
#else
unsigned long opt = 1;
ioctlsocket(fd, FIONBIO, &opt);
#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 */
void slirp_pstrcpy(char *buf, int buf_size, const char *str)
{
int c;
char *q = buf;
if (buf_size <= 0)
return;
for(;;) {
c = *str++;
if (c == 0 || q >= buf + buf_size - 1)
break;
*q++ = c;
}
*q = '\0';
}

127
slirp/util.h Normal file
View file

@ -0,0 +1,127 @@
/*
* Copyright (c) 2003-2008 Fabrice Bellard
* Copyright (c) 2010-2019 Red Hat, Inc.
*
* 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.
*/
#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
#ifndef DIV_ROUND_UP
#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
#endif
#ifndef container_of
#define container_of(ptr, type, member) __extension__ ({ \
void *__mptr = (void *)(ptr); \
((type *)(__mptr - offsetof(type, member))); })
#endif
#if defined(_WIN32) /* CONFIG_IOVEC */
# if !defined(IOV_MAX) /* XXX: to avoid duplicate with QEMU osdep.h */
struct iovec {
void *iov_base;
size_t iov_len;
};
# endif
#else
#include <sys/uio.h>
#endif
#define SCALE_MS 1000000
#define ETH_ALEN 6
#define ETH_HLEN 14
#define ETH_P_IP (0x0800) /* Internet Protocol packet */
#define ETH_P_ARP (0x0806) /* Address Resolution packet */
#define ETH_P_IPV6 (0x86dd)
#define ETH_P_VLAN (0x8100)
#define ETH_P_DVLAN (0x88a8)
#define ETH_P_NCSI (0x88f8)
#define ETH_P_UNKNOWN (0xffff)
#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);
void slirp_set_nonblock(int fd);
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
}
void slirp_pstrcpy(char *buf, int buf_size, const char *str);
#endif

View file

@ -26,14 +26,13 @@ stub-obj-y += qtest.o
stub-obj-y += replay.o
stub-obj-y += runstate-check.o
stub-obj-y += set-fd-handler.o
stub-obj-y += slirp.o
stub-obj-y += sysbus.o
stub-obj-y += tpm.o
stub-obj-y += trace-control.o
stub-obj-y += uuid.o
stub-obj-y += vm-stop.o
stub-obj-y += vmstate.o
stub-obj-$(CONFIG_WIN32) += fd-register.o
stub-obj-y += fd-register.o
stub-obj-y += qmp_memory_device.o
stub-obj-y += target-monitor-defs.o
stub-obj-y += target-get-monitor-def.o

View file

@ -1,13 +0,0 @@
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "qemu/host-utils.h"
#include "slirp/libslirp.h"
void slirp_pollfds_fill(GArray *pollfds, uint32_t *timeout)
{
}
void slirp_pollfds_poll(GArray *pollfds, int select_error)
{
}

View file

@ -469,25 +469,42 @@ static int os_host_main_loop_wait(int64_t timeout)
}
#endif
static NotifierList main_loop_poll_notifiers =
NOTIFIER_LIST_INITIALIZER(main_loop_poll_notifiers);
void main_loop_poll_add_notifier(Notifier *notify)
{
notifier_list_add(&main_loop_poll_notifiers, notify);
}
void main_loop_poll_remove_notifier(Notifier *notify)
{
notifier_remove(notify);
}
void main_loop_wait(int nonblocking)
{
MainLoopPoll mlpoll = {
.state = MAIN_LOOP_POLL_FILL,
.timeout = UINT32_MAX,
.pollfds = gpollfds,
};
int ret;
uint32_t timeout = UINT32_MAX;
int64_t timeout_ns;
if (nonblocking) {
timeout = 0;
mlpoll.timeout = 0;
}
/* poll any events */
g_array_set_size(gpollfds, 0); /* reset for new iteration */
/* XXX: separate device handlers from system ones */
slirp_pollfds_fill(gpollfds, &timeout);
notifier_list_notify(&main_loop_poll_notifiers, &mlpoll);
if (timeout == UINT32_MAX) {
if (mlpoll.timeout == UINT32_MAX) {
timeout_ns = -1;
} else {
timeout_ns = (uint64_t)timeout * (int64_t)(SCALE_MS);
timeout_ns = (uint64_t)mlpoll.timeout * (int64_t)(SCALE_MS);
}
timeout_ns = qemu_soonest_timeout(timeout_ns,
@ -495,7 +512,8 @@ void main_loop_wait(int nonblocking)
&main_loop_tlg));
ret = os_host_main_loop_wait(timeout_ns);
slirp_pollfds_poll(gpollfds, (ret < 0));
mlpoll.state = ret < 0 ? MAIN_LOOP_POLL_ERR : MAIN_LOOP_POLL_OK;
notifier_list_notify(&main_loop_poll_notifiers, &mlpoll);
/* CPU thread can infinitely wait for event after
missing the warp */

View file

@ -29,7 +29,7 @@
#include <sys/statvfs.h>
/* See MySQL bug #7156 (http://bugs.mysql.com/bug.php?id=7156) for
discussion about Solaris header problems */
extern int madvise(caddr_t, size_t, int);
extern int madvise(char *, size_t, int);
#endif
#include "qemu-common.h"