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:
commit
e47f81b617
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
185
net/slirp.c
185
net/slirp.c
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 =
|
||||
|
@ -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)
|
||||
|
@ -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"
|
||||
|
||||
/*
|
||||
|
@ -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_ */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,6 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "slirp.h"
|
||||
|
||||
static const uint8_t RFC3397_OPT_DOMAIN_SEARCH = 119;
|
||||
|
@ -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;
|
||||
|
||||
|
17
slirp/ip.h
17
slirp/ip.h
@ -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
|
||||
|
14
slirp/ip6.h
14
slirp/ip6.h
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -3,7 +3,6 @@
|
||||
* Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "slirp.h"
|
||||
#include "ip6_icmp.h"
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
||||
|
@ -15,7 +15,6 @@
|
||||
* the flags
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "slirp.h"
|
||||
|
||||
#define MBUF_THRESH 30
|
||||
|
@ -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;
|
||||
|
124
slirp/misc.c
124
slirp/misc.c
@ -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;
|
||||
}
|
||||
|
||||
|
15
slirp/misc.h
15
slirp/misc.h
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
193
slirp/qtailq.h
Normal 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 */
|
@ -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
|
||||
|
@ -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 *);
|
||||
|
1065
slirp/slirp.c
1065
slirp/slirp.c
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
394
slirp/state.c
Normal 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
9
slirp/state.h
Normal 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_ */
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
16
slirp/tftp.c
16
slirp/tftp.c
@ -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) {
|
||||
|
@ -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"
|
16
slirp/udp.c
16
slirp/udp.c
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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
207
slirp/util.c
Normal 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
127
slirp/util.h
Normal 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
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user