Next set of updates from libslirp.
- Started implementing guest forwarding feature. - Updated most of socket.h. - Added if_mtu / if_mru handling. - Cleaned up MIN / MAX defines.
This commit is contained in:
parent
b84ebf5dfc
commit
a684734975
@ -35,5 +35,8 @@
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -224,11 +224,15 @@ void slirp_pollfds_poll(Slirp *slirp, int select_error,
|
||||
* guest network, to be interpreted by slirp. */
|
||||
void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len);
|
||||
|
||||
/* This is called by the application when a timer expires, if it provides
|
||||
* the timer_new_opaque callback. It is not needed if the application only
|
||||
* uses timer_new. */
|
||||
void slirp_handle_timer(Slirp *slirp, SlirpTimerId id, void *cb_opaque);
|
||||
|
||||
/* These set up / remove port forwarding between a host port in the real world
|
||||
* and the guest network. */
|
||||
int slirp_add_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
|
||||
int host_port, 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);
|
||||
|
||||
@ -237,6 +241,14 @@ int slirp_remove_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
|
||||
int slirp_add_exec(Slirp *slirp, const char *cmdline,
|
||||
struct in_addr *guest_addr, int guest_port);
|
||||
|
||||
/* Set up port forwarding between a port in the guest network and a
|
||||
* callback that will receive the data coming from the port */
|
||||
int slirp_add_guestfwd(Slirp *slirp, SlirpWriteCb write_cb, void *opaque,
|
||||
struct in_addr *guest_addr, int guest_port);
|
||||
|
||||
/* TODO: rather identify a guestfwd through an opaque pointer instead of through
|
||||
* the guest_addr */
|
||||
|
||||
/* This is called by the application for a guestfwd, to determine how much data
|
||||
* can be received by the forwarded port through a call to slirp_socket_recv. */
|
||||
size_t slirp_socket_can_recv(Slirp *slirp, struct in_addr guest_addr,
|
||||
@ -246,10 +258,14 @@ size_t slirp_socket_can_recv(Slirp *slirp, struct in_addr guest_addr,
|
||||
void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr, int guest_port,
|
||||
const uint8_t *buf, int size);
|
||||
|
||||
/* Remove entries added by slirp_add_exec, slirp_add_unix or slirp_add_guestfwd */
|
||||
int slirp_remove_guestfwd(Slirp *slirp, struct in_addr guest_addr,
|
||||
int guest_port);
|
||||
|
||||
/* Return the version of the slirp implementation */
|
||||
const char *slirp_version_string(void);
|
||||
|
||||
/* you must provide the following functions: */
|
||||
void slirp_warning(const char *, void *);
|
||||
|
||||
#endif
|
||||
#endif /* LIBSLIRP_H */
|
||||
|
@ -91,7 +91,7 @@ m_get(Slirp *slirp)
|
||||
m->m_len = 0;
|
||||
m->m_nextpkt = NULL;
|
||||
m->m_prevpkt = NULL;
|
||||
m->arp_requested = false;
|
||||
m->resolution_requested = false;
|
||||
m->expiration_date = (uint64_t)-1;
|
||||
end_error:
|
||||
DEBUG_ARG("m = %lx", (long )m);
|
||||
|
@ -79,14 +79,14 @@ struct mbuf {
|
||||
char *m_data; /* Location of data */
|
||||
int m_len; /* Amount of data in this mbuf */
|
||||
|
||||
Slirp *slirp;
|
||||
bool arp_requested;
|
||||
uint64_t expiration_date;
|
||||
/* start of dynamic buffer area, must be last element */
|
||||
union {
|
||||
char m_dat[1]; /* ANSI don't like 0 sized arrays */
|
||||
char *m_ext;
|
||||
};
|
||||
Slirp *slirp;
|
||||
bool resolution_requested;
|
||||
uint64_t expiration_date;
|
||||
/* start of dynamic buffer area, must be last element */
|
||||
union {
|
||||
char m_dat[1]; /* ANSI don't like 0 sized arrays */
|
||||
char *m_ext;
|
||||
};
|
||||
};
|
||||
|
||||
#define ifq_prev m_prev
|
||||
|
@ -4,16 +4,10 @@
|
||||
*/
|
||||
|
||||
#include "slirp.h"
|
||||
#include "libslirp.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
|
||||
#if BX_NETWORKING && BX_NETMOD_SLIRP
|
||||
|
||||
#ifdef DEBUG
|
||||
int slirp_debug = DBG_CALL|DBG_MISC|DBG_ERROR;
|
||||
#ifndef _WIN32
|
||||
#include <sys/un.h>
|
||||
#endif
|
||||
|
||||
void slirp_insque(void *a, void *b)
|
||||
@ -35,187 +29,66 @@ void slirp_remque(void *a)
|
||||
element->qh_rlink = NULL;
|
||||
}
|
||||
|
||||
int add_exec(struct gfwd_list **ex_ptr, const char *exec, struct in_addr addr, int port)
|
||||
/* TODO: IPv6 */
|
||||
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 = (struct gfwd_list *)malloc(sizeof(struct gfwd_list));
|
||||
|
||||
/* First, check if the port is "bound" */
|
||||
for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) {
|
||||
if (port == tmp_ptr->ex_fport &&
|
||||
addr.s_addr == tmp_ptr->ex_addr.s_addr)
|
||||
return -1;
|
||||
}
|
||||
f->write_cb = write_cb;
|
||||
f->opaque = opaque;
|
||||
f->ex_fport = port;
|
||||
f->ex_addr = addr;
|
||||
f->ex_next = *ex_ptr;
|
||||
*ex_ptr = f;
|
||||
|
||||
tmp_ptr = *ex_ptr;
|
||||
*ex_ptr = (struct gfwd_list *)malloc(sizeof(struct gfwd_list));
|
||||
(*ex_ptr)->ex_fport = port;
|
||||
(*ex_ptr)->ex_addr = addr;
|
||||
(*ex_ptr)->ex_exec = strdup(exec);
|
||||
(*ex_ptr)->ex_next = tmp_ptr;
|
||||
return 0;
|
||||
return f;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
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);
|
||||
|
||||
int
|
||||
fork_exec(struct socket *so, const char *ex, int do_pty)
|
||||
f->ex_exec = strdup(cmdline);
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
struct gfwd_list *add_unix(struct gfwd_list **ex_ptr, const char *unixsock,
|
||||
struct in_addr addr, int port)
|
||||
{
|
||||
struct gfwd_list *f = add_guestfwd(ex_ptr, NULL, NULL, addr, port);
|
||||
|
||||
f->ex_unix = strdup(unixsock);
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
int remove_guestfwd(struct gfwd_list **ex_ptr, struct in_addr addr, int port)
|
||||
{
|
||||
for (; *ex_ptr != NULL; ex_ptr = &((*ex_ptr)->ex_next)) {
|
||||
struct gfwd_list *f = *ex_ptr;
|
||||
if (f->ex_addr.s_addr == addr.s_addr && f->ex_fport == port) {
|
||||
*ex_ptr = f->ex_next;
|
||||
free(f->ex_exec);
|
||||
free(f);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int fork_exec(struct socket *so, const char *ex)
|
||||
{
|
||||
/* not implemented */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* XXX This is ugly
|
||||
* We create and bind a socket, then fork off to another
|
||||
* process, which connects to this socket, after which we
|
||||
* exec the wanted program. If something (strange) happens,
|
||||
* the accept() call could block us forever.
|
||||
*
|
||||
* do_pty = 0 Fork/exec inetd style
|
||||
* do_pty = 1 Fork/exec using slirp.telnetd
|
||||
* do_ptr = 2 Fork/exec using pty
|
||||
*/
|
||||
int
|
||||
fork_exec(struct socket *so, const char *ex, int do_pty)
|
||||
int open_unix(struct socket *so, const char *unixpath)
|
||||
{
|
||||
int s;
|
||||
struct sockaddr_in addr;
|
||||
socklen_t addrlen = sizeof(addr);
|
||||
int opt;
|
||||
const char *argv[256];
|
||||
/* don't want to clobber the original */
|
||||
char *bptr;
|
||||
const char *curarg;
|
||||
int c, i, ret;
|
||||
pid_t pid;
|
||||
|
||||
DEBUG_CALL("fork_exec");
|
||||
DEBUG_ARG("so = %lx", (long)so);
|
||||
DEBUG_ARG("ex = %lx", (long)ex);
|
||||
DEBUG_ARG("do_pty = %lx", (long)do_pty);
|
||||
|
||||
if (do_pty == 2) {
|
||||
return 0;
|
||||
} else {
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = 0;
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
if ((s = slirp_socket(AF_INET, SOCK_STREAM, 0)) < 0 ||
|
||||
bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||
|
||||
listen(s, 1) < 0) {
|
||||
#ifdef DEBUG
|
||||
printf("Error: inet socket: %s\n", strerror(errno));
|
||||
#endif
|
||||
closesocket(s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
switch(pid) {
|
||||
case -1:
|
||||
#ifdef DEBUG
|
||||
printf("Error: fork failed: %s\n", strerror(errno));
|
||||
#endif
|
||||
close(s);
|
||||
return 0;
|
||||
|
||||
case 0:
|
||||
setsid();
|
||||
|
||||
/* Set the DISPLAY */
|
||||
getsockname(s, (struct sockaddr *)&addr, &addrlen);
|
||||
close(s);
|
||||
/*
|
||||
* Connect to the socket
|
||||
* XXX If any of these fail, we're in trouble!
|
||||
*/
|
||||
s = slirp_socket(AF_INET, SOCK_STREAM, 0);
|
||||
addr.sin_addr = loopback_addr;
|
||||
do {
|
||||
ret = connect(s, (struct sockaddr *)&addr, addrlen);
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
|
||||
dup2(s, 0);
|
||||
dup2(s, 1);
|
||||
dup2(s, 2);
|
||||
#ifdef __ANDROID__
|
||||
{
|
||||
/* No getdtablesize() on Android, we will use /proc/XXX/fd/ Linux virtual FS instead */
|
||||
char proc_fd_path[256];
|
||||
sprintf(proc_fd_path, "/proc/%u/fd", (unsigned)getpid());
|
||||
DIR *proc_dir = opendir(proc_fd_path);
|
||||
if (proc_dir) {
|
||||
for (struct dirent *fd = readdir(proc_dir); fd != NULL; fd = readdir(proc_dir)) {
|
||||
if (atoi(fd->d_name) >= 3 && fd->d_name[0] != '.') /* ".." and "." will return 0 anyway */
|
||||
close(atoi(fd->d_name));
|
||||
}
|
||||
closedir(proc_dir);
|
||||
}
|
||||
}
|
||||
#else
|
||||
for (s = getdtablesize() - 1; s >= 3; s--)
|
||||
close(s);
|
||||
#endif
|
||||
|
||||
i = 0;
|
||||
bptr = strdup(ex); /* No need to free() this */
|
||||
if (do_pty == 1) {
|
||||
/* Setup "slirp.telnetd -x" */
|
||||
argv[i++] = "slirp.telnetd";
|
||||
argv[i++] = "-x";
|
||||
argv[i++] = bptr;
|
||||
} else
|
||||
do {
|
||||
/* Change the string into argv[] */
|
||||
curarg = bptr;
|
||||
while (*bptr != ' ' && *bptr != (char)0)
|
||||
bptr++;
|
||||
c = *bptr;
|
||||
*bptr++ = (char)0;
|
||||
argv[i++] = strdup(curarg);
|
||||
} while (c);
|
||||
|
||||
argv[i] = NULL;
|
||||
execvp(argv[0], (char **)argv);
|
||||
|
||||
/* Ooops, failed, let's tell the user why */
|
||||
fprintf(stderr, "Error: execvp of %s failed: %s\n",
|
||||
argv[0], strerror(errno));
|
||||
close(0); close(1); close(2); /* XXX */
|
||||
exit(1);
|
||||
|
||||
default:
|
||||
slirp_warning("qemu_add_child_watch(pid) not implemented", so->slirp->opaque);
|
||||
/*
|
||||
* XXX this could block us...
|
||||
* XXX Should set a timer here, and if accept() doesn't
|
||||
* return after X seconds, declare it a failure
|
||||
* The only reason this will block forever is if socket()
|
||||
* of connect() fail in the child process
|
||||
*/
|
||||
do {
|
||||
so->s = accept(s, (struct sockaddr *)&addr, &addrlen);
|
||||
} while (so->s < 0 && errno == EINTR);
|
||||
closesocket(s);
|
||||
slirp_socket_set_fast_reuse(so->s);
|
||||
opt = 1;
|
||||
setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
|
||||
slirp_set_nonblock(so->s);
|
||||
|
||||
/* Append the telnet options now */
|
||||
if (so->so_m != NULL && do_pty == 1) {
|
||||
sbappend(so, so->so_m);
|
||||
so->so_m = NULL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
/* not implemented */
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -6,10 +6,15 @@
|
||||
#ifndef MISC_H
|
||||
#define MISC_H
|
||||
|
||||
#include "libslirp.h"
|
||||
|
||||
struct gfwd_list {
|
||||
struct in_addr ex_addr; /* Server address */
|
||||
int ex_fport; /* Port to telnet to */
|
||||
const char *ex_exec; /* Command line of what to exec */
|
||||
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 */
|
||||
char *ex_unix; /* unix socket */
|
||||
struct gfwd_list *ex_next;
|
||||
};
|
||||
|
||||
@ -53,7 +58,28 @@ void slirp_insque(void *a, void *b);
|
||||
/* Remove element a from its queue */
|
||||
void slirp_remque(void *a);
|
||||
|
||||
int add_exec(struct gfwd_list **, const char *, struct in_addr, int);
|
||||
int fork_exec(struct socket *so, const char *ex, int do_pty);
|
||||
/* Run the given command in the background, and expose its output as a socket */
|
||||
int fork_exec(struct socket *so, const char *ex);
|
||||
|
||||
/* Create a Unix socket, and expose it as a socket */
|
||||
int open_unix(struct socket *so, const char *unixsock);
|
||||
|
||||
/* Add a guest forward on the given address and port, with guest data being
|
||||
* forwarded by calling write_cb */
|
||||
struct gfwd_list *add_guestfwd(struct gfwd_list **ex_ptr, SlirpWriteCb write_cb,
|
||||
void *opaque, struct in_addr addr, int port);
|
||||
|
||||
/* Run the given command in the backaground, and send its output to the guest on
|
||||
* the given address and port */
|
||||
struct gfwd_list *add_exec(struct gfwd_list **ex_ptr, const char *cmdline,
|
||||
struct in_addr addr, int port);
|
||||
|
||||
/* Create a Unix socket, and expose it to the guest on the given address and
|
||||
* port */
|
||||
struct gfwd_list *add_unix(struct gfwd_list **ex_ptr, const char *unixsock,
|
||||
struct in_addr addr, int port);
|
||||
|
||||
/* Remove the guest forward bound to the given address and port */
|
||||
int remove_guestfwd(struct gfwd_list **ex_ptr, struct in_addr addr, int port);
|
||||
|
||||
#endif
|
||||
|
@ -28,6 +28,15 @@
|
||||
|
||||
#if BX_NETWORKING && BX_NETMOD_SLIRP
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <net/if.h>
|
||||
#endif
|
||||
|
||||
/* https://gitlab.freedesktop.org/slirp/libslirp/issues/18 */
|
||||
#if defined(__NetBSD__) && defined(if_mtu)
|
||||
#undef if_mtu
|
||||
#endif
|
||||
|
||||
int slirp_debug;
|
||||
|
||||
/* host loopback address */
|
||||
@ -250,7 +259,8 @@ Slirp *slirp_new(const SlirpConfig *cfg, const SlirpCb *callbacks, void *opaque)
|
||||
if (cfg->vdnssearch) {
|
||||
translate_dnssearch(slirp, cfg->vdnssearch);
|
||||
}
|
||||
|
||||
slirp->if_mtu = cfg->if_mtu == 0 ? IF_MTU_DEFAULT : cfg->if_mtu;
|
||||
slirp->if_mru = cfg->if_mru == 0 ? IF_MRU_DEFAULT : cfg->if_mru;
|
||||
slirp->disable_host_loopback = cfg->disable_host_loopback;
|
||||
slirp->enable_emu = cfg->enable_emu;
|
||||
|
||||
@ -679,7 +689,7 @@ void slirp_pollfds_poll(Slirp *slirp, int select_error,
|
||||
static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
|
||||
{
|
||||
struct slirp_arphdr *ah = (struct slirp_arphdr *)(pkt + ETH_HLEN);
|
||||
uint8_t arp_reply[max(ETH_HLEN + sizeof(struct slirp_arphdr), 64)];
|
||||
uint8_t arp_reply[MAX(ETH_HLEN + sizeof(struct slirp_arphdr), 64)];
|
||||
struct ethhdr *reh = (struct ethhdr *)arp_reply;
|
||||
struct slirp_arphdr *rah = (struct slirp_arphdr *)(arp_reply + ETH_HLEN);
|
||||
int ar_op;
|
||||
@ -774,26 +784,21 @@ void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
|
||||
}
|
||||
}
|
||||
|
||||
/* Output the IP packet to the ethernet device. Returns 0 if the packet must be
|
||||
* re-queued.
|
||||
/* Prepare the IPv4 packet to be sent to the ethernet device. Returns 1 if no
|
||||
* packet should be sent, 0 if the packet must be re-queued, 2 if the packet
|
||||
* is ready to go.
|
||||
*/
|
||||
int if_encap(Slirp *slirp, struct mbuf *ifm)
|
||||
static int if_encap4(Slirp *slirp, struct mbuf *ifm, struct ethhdr *eh,
|
||||
uint8_t ethaddr[ETH_ALEN])
|
||||
{
|
||||
uint8_t buf[1600];
|
||||
struct ethhdr *eh = (struct ethhdr *)buf;
|
||||
uint8_t ethaddr[ETH_ALEN];
|
||||
const struct ip *iph = (const struct ip *)ifm->m_data;
|
||||
|
||||
if (ifm->m_len + ETH_HLEN > (int)sizeof(buf)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!arp_table_search(slirp, iph->ip_dst.s_addr, ethaddr)) {
|
||||
uint8_t arp_req[ETH_HLEN + sizeof(struct slirp_arphdr)];
|
||||
struct ethhdr *reh = (struct ethhdr *)arp_req;
|
||||
struct slirp_arphdr *rah = (struct slirp_arphdr *)(arp_req + ETH_HLEN);
|
||||
uint8_t arp_req[2 + ETH_HLEN + sizeof(struct slirp_arphdr)];
|
||||
struct ethhdr *reh = (struct ethhdr *)(arp_req + 2);
|
||||
struct slirp_arphdr *rah = (struct slirp_arphdr *)(arp_req + 2 + ETH_HLEN);
|
||||
|
||||
if (!ifm->arp_requested) {
|
||||
if (!ifm->resolution_requested) {
|
||||
/* If the client addr is not known, send an ARP request */
|
||||
memset(reh->h_dest, 0xff, ETH_ALEN);
|
||||
memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
|
||||
@ -818,23 +823,79 @@ int if_encap(Slirp *slirp, struct mbuf *ifm)
|
||||
/* target IP */
|
||||
rah->ar_tip = iph->ip_dst.s_addr;
|
||||
slirp->client_ipaddr = iph->ip_dst;
|
||||
slirp_send_packet_all(slirp, arp_req, sizeof(arp_req));
|
||||
ifm->arp_requested = true;
|
||||
slirp_send_packet_all(slirp, arp_req + 2, sizeof(arp_req) - 2);
|
||||
ifm->resolution_requested = true;
|
||||
|
||||
/* Expire request and drop outgoing packet after 1 second */
|
||||
ifm->expiration_date = slirp->cb->clock_get_ns(slirp->opaque) + 1000000000ULL;
|
||||
ifm->expiration_date =
|
||||
slirp->cb->clock_get_ns(slirp->opaque) + 1000000000ULL;
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
memcpy(eh->h_dest, ethaddr, ETH_ALEN);
|
||||
memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 4);
|
||||
/* XXX: not correct */
|
||||
memcpy(&eh->h_source[2], &slirp->vhost_addr, 4);
|
||||
eh->h_proto = htons(ETH_P_IP);
|
||||
memcpy(buf + sizeof(struct ethhdr), ifm->m_data, ifm->m_len);
|
||||
slirp_send_packet_all(slirp, buf, ifm->m_len + ETH_HLEN);
|
||||
|
||||
/* Send this */
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Prepare the IPv6 packet to be sent to the ethernet device. Returns 1 if no
|
||||
* packet should be sent, 0 if the packet must be re-queued, 2 if the packet
|
||||
* is ready to go.
|
||||
*/
|
||||
static int if_encap6(Slirp *slirp, struct mbuf *ifm, struct ethhdr *eh,
|
||||
uint8_t ethaddr[ETH_ALEN])
|
||||
{
|
||||
slirp_warning("IPv6 packet not supported yet", slirp->opaque);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Output the IP packet to the ethernet device. Returns 0 if the packet must be
|
||||
* re-queued.
|
||||
*/
|
||||
int if_encap(Slirp *slirp, struct mbuf *ifm)
|
||||
{
|
||||
uint8_t buf[IF_MTU_MAX + 100];
|
||||
struct ethhdr *eh = (struct ethhdr *)(buf + 2);
|
||||
uint8_t ethaddr[ETH_ALEN];
|
||||
const struct ip *iph = (const struct ip *)ifm->m_data;
|
||||
int ret;
|
||||
// char ethaddr_str[ETH_ADDRSTRLEN];
|
||||
|
||||
if (ifm->m_len + ETH_HLEN > (int)sizeof(buf) - 2) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (iph->ip_v) {
|
||||
case IPVERSION:
|
||||
ret = if_encap4(slirp, ifm, eh, ethaddr);
|
||||
if (ret < 2) {
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
case IP6VERSION:
|
||||
ret = if_encap6(slirp, ifm, eh, ethaddr);
|
||||
if (ret < 2) {
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
slirp_warning("unknown protocol", slirp->opaque);
|
||||
}
|
||||
|
||||
memcpy(eh->h_dest, ethaddr, ETH_ALEN);
|
||||
DEBUG_ARG("src = %s", slirp_ether_ntoa(eh->h_source, ethaddr_str,
|
||||
sizeof(ethaddr_str)));
|
||||
DEBUG_ARG("dst = %s", slirp_ether_ntoa(eh->h_dest, ethaddr_str,
|
||||
sizeof(ethaddr_str)));
|
||||
memcpy(buf + 2 + sizeof(struct ethhdr), ifm->m_data, ifm->m_len);
|
||||
slirp_send_packet_all(slirp, buf + 2, ifm->m_len + ETH_HLEN);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Drop host forwarding rule, return 0 if found. */
|
||||
@ -880,32 +941,99 @@ int slirp_add_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO: IPv6 */
|
||||
static bool check_guestfwd(Slirp *slirp, struct in_addr *guest_addr,
|
||||
int guest_port)
|
||||
{
|
||||
struct gfwd_list *tmp_ptr;
|
||||
|
||||
if (!guest_addr->s_addr) {
|
||||
guest_addr->s_addr = slirp->vnetwork_addr.s_addr |
|
||||
(htonl(0x0204) & ~slirp->vnetwork_mask.s_addr);
|
||||
}
|
||||
if ((guest_addr->s_addr & slirp->vnetwork_mask.s_addr) !=
|
||||
slirp->vnetwork_addr.s_addr ||
|
||||
guest_addr->s_addr == slirp->vhost_addr.s_addr ||
|
||||
guest_addr->s_addr == slirp->vnameserver_addr.s_addr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* check if the port is "bound" */
|
||||
for (tmp_ptr = slirp->guestfwd_list; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) {
|
||||
if (guest_port == tmp_ptr->ex_fport &&
|
||||
guest_addr->s_addr == tmp_ptr->ex_addr.s_addr)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int slirp_add_exec(Slirp *slirp, const char *cmdline,
|
||||
struct in_addr *guest_addr, int guest_port)
|
||||
{
|
||||
if (!guest_addr->s_addr) {
|
||||
guest_addr->s_addr = slirp->vnetwork_addr.s_addr |
|
||||
(htonl(0x0204) & ~slirp->vnetwork_mask.s_addr);
|
||||
}
|
||||
if ((guest_addr->s_addr & slirp->vnetwork_mask.s_addr) !=
|
||||
slirp->vnetwork_addr.s_addr ||
|
||||
guest_addr->s_addr == slirp->vhost_addr.s_addr ||
|
||||
guest_addr->s_addr == slirp->vnameserver_addr.s_addr) {
|
||||
if (!check_guestfwd(slirp, guest_addr, guest_port)) {
|
||||
return -1;
|
||||
}
|
||||
return add_exec(&slirp->guestfwd_list, cmdline, *guest_addr,
|
||||
htons(guest_port));
|
||||
|
||||
add_exec(&slirp->guestfwd_list, cmdline, *guest_addr, htons(guest_port));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int slirp_add_unix(Slirp *slirp, const char *unixsock,
|
||||
struct in_addr *guest_addr, int guest_port)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
if (!check_guestfwd(slirp, guest_addr, guest_port)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
add_unix(&slirp->guestfwd_list, unixsock, *guest_addr, htons(guest_port));
|
||||
return 0;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int slirp_add_guestfwd(Slirp *slirp, SlirpWriteCb write_cb, void *opaque,
|
||||
struct in_addr *guest_addr, int guest_port)
|
||||
{
|
||||
if (!check_guestfwd(slirp, guest_addr, guest_port)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
add_guestfwd(&slirp->guestfwd_list, write_cb, opaque, *guest_addr,
|
||||
htons(guest_port));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int slirp_remove_guestfwd(Slirp *slirp, struct in_addr guest_addr,
|
||||
int guest_port)
|
||||
{
|
||||
return remove_guestfwd(&slirp->guestfwd_list, guest_addr,
|
||||
htons(guest_port));
|
||||
}
|
||||
|
||||
slirp_ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)
|
||||
{
|
||||
if (so->s == -1 && so->extra) {
|
||||
Slirp *slirp = so->slirp;
|
||||
slirp_warning("slirp_send(): so->extra not supported", slirp->opaque);
|
||||
if (so->s == -1 && so->guestfwd) {
|
||||
/* XXX this blocks entire thread. Rewrite to use
|
||||
* qemu_chr_fe_write and background I/O callbacks */
|
||||
so->guestfwd->write_cb(buf, len, so->guestfwd->opaque);
|
||||
return len;
|
||||
}
|
||||
|
||||
return send(so->s, (const char*)buf, len, flags);
|
||||
if (so->s == -1) {
|
||||
/*
|
||||
* This should in theory not happen but it is hard to be
|
||||
* sure because some code paths will end up with so->s == -1
|
||||
* on a failure but don't dispose of the struct socket.
|
||||
* Check specifically, so we don't pass -1 to send().
|
||||
*/
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return send(so->s, buf, len, flags);
|
||||
}
|
||||
|
||||
struct socket *slirp_find_ctl_socket(Slirp *slirp, struct in_addr guest_addr,
|
||||
|
@ -110,6 +110,7 @@ void arp_table_add(Slirp *slirp, uint32_t ip_addr,
|
||||
bool arp_table_search(Slirp *slirp, uint32_t ip_addr,
|
||||
uint8_t out_ethaddr[ETH_ALEN]);
|
||||
|
||||
/* Slirp configuration, specified by the application */
|
||||
struct Slirp {
|
||||
int cfg_version;
|
||||
|
||||
@ -137,6 +138,9 @@ struct Slirp {
|
||||
int restricted;
|
||||
struct gfwd_list *guestfwd_list;
|
||||
|
||||
int if_mtu;
|
||||
int if_mru;
|
||||
|
||||
bool disable_host_loopback;
|
||||
|
||||
/* mbuf states */
|
||||
@ -244,16 +248,4 @@ struct tcpcb *tcp_drop(struct tcpcb *tp, int err);
|
||||
/* Send a frame to the virtual Ethernet board, i.e. call the application send_packet callback */
|
||||
void slirp_send_packet_all(Slirp *slirp, const void *buf, size_t len);
|
||||
|
||||
#ifndef min
|
||||
#define min(x,y) ((x) < (y) ? (x) : (y))
|
||||
#endif
|
||||
#ifndef max
|
||||
#define max(x,y) ((x) > (y) ? (x) : (y))
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#undef errno
|
||||
#define errno (WSAGetLastError())
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -29,12 +29,6 @@
|
||||
#define HAVE_SYS_SELECT_H
|
||||
#endif
|
||||
|
||||
/* Define to whatever your compiler thinks inline should be */
|
||||
//#define inline inline
|
||||
|
||||
/* Define to whatever your compiler thinks const should be */
|
||||
//#define const const
|
||||
|
||||
/* Define to sizeof(char) */
|
||||
#define SIZEOF_CHAR 1
|
||||
|
||||
|
@ -62,12 +62,13 @@ socreate(Slirp *slirp)
|
||||
void
|
||||
sofree(struct socket *so)
|
||||
{
|
||||
Slirp *slirp = so->slirp;
|
||||
|
||||
if (so->so_emu==EMU_RSH && so->extra) {
|
||||
sofree((struct socket*)so->extra);
|
||||
so->extra=NULL;
|
||||
}
|
||||
Slirp *slirp = so->slirp;
|
||||
/*
|
||||
if (so->so_emu==EMU_RSH && so->extra) {
|
||||
sofree((struct socket*)so->extra);
|
||||
so->extra=NULL;
|
||||
}
|
||||
*/
|
||||
if (so == slirp->tcp_last_so) {
|
||||
slirp->tcp_last_so = &slirp->tcb;
|
||||
} else if (so == slirp->udp_last_so) {
|
||||
@ -316,12 +317,12 @@ sosendoob(struct socket *so)
|
||||
* send it all
|
||||
*/
|
||||
len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr;
|
||||
if (len > so->so_urgc) len = so->so_urgc;
|
||||
if (len > (int)so->so_urgc) len = so->so_urgc;
|
||||
memcpy(buff, sb->sb_rptr, len);
|
||||
so->so_urgc -= len;
|
||||
if (so->so_urgc) {
|
||||
n = sb->sb_wptr - sb->sb_data;
|
||||
if (n > so->so_urgc) n = so->so_urgc;
|
||||
if (n > (int)so->so_urgc) n = so->so_urgc;
|
||||
memcpy((buff + len), sb->sb_data, n);
|
||||
so->so_urgc -= n;
|
||||
len += n;
|
||||
|
@ -3,58 +3,89 @@
|
||||
* Copyright (c) 1995 Danny Gasparovski.
|
||||
*/
|
||||
|
||||
#ifndef SLIRP_SOCKET_H
|
||||
#define SLIRP_SOCKET_H
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/un.h>
|
||||
#endif
|
||||
|
||||
#ifndef SLIRP_SOCKET_H
|
||||
#define SLIRP_SOCKET_H
|
||||
#include "misc.h"
|
||||
#include "sbuf.h"
|
||||
|
||||
#define SO_EXPIRE 240000
|
||||
#define SO_EXPIREFAST 10000
|
||||
|
||||
/* Helps unify some in/in6 routines. */
|
||||
union in4or6_addr {
|
||||
struct in_addr addr4;
|
||||
struct in6_addr addr6;
|
||||
};
|
||||
typedef union in4or6_addr in4or6_addr;
|
||||
|
||||
/*
|
||||
* Our socket structure
|
||||
*/
|
||||
|
||||
union slirp_sockaddr {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_storage ss;
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_in6 sin6;
|
||||
};
|
||||
|
||||
struct socket {
|
||||
struct socket *so_next,*so_prev; /* For a linked list of sockets */
|
||||
struct socket *so_next, *so_prev; /* For a linked list of sockets */
|
||||
|
||||
int s; /* The actual socket */
|
||||
int s; /* The actual socket */
|
||||
int s_aux; /* An auxiliary socket for miscellaneous use. Currently used to
|
||||
* reserve OS ports in UNIX-to-inet translation. */
|
||||
struct gfwd_list *guestfwd;
|
||||
|
||||
int pollfds_idx;
|
||||
int pollfds_idx;
|
||||
|
||||
Slirp *slirp; /* managing slirp instance */
|
||||
Slirp *slirp; /* managing slirp instance */
|
||||
|
||||
/* XXX union these with not-yet-used sbuf params */
|
||||
struct mbuf *so_m; /* Pointer to the original SYN packet,
|
||||
* for non-blocking connect()'s, and
|
||||
* PING reply's */
|
||||
struct tcpiphdr *so_ti; /* Pointer to the original ti within
|
||||
* so_mconn, for non-blocking connections */
|
||||
int so_urgc;
|
||||
struct in_addr so_faddr; /* foreign host table entry */
|
||||
struct in_addr so_laddr; /* local host table entry */
|
||||
uint16_t so_fport; /* foreign port */
|
||||
uint16_t so_lport; /* local port */
|
||||
/* XXX union these with not-yet-used sbuf params */
|
||||
struct mbuf *so_m; /* Pointer to the original SYN packet,
|
||||
* for non-blocking connect()'s, and
|
||||
* PING reply's */
|
||||
struct tcpiphdr *so_ti; /* Pointer to the original ti within
|
||||
* so_mconn, for non-blocking connections */
|
||||
uint32_t so_urgc;
|
||||
union slirp_sockaddr fhost; /* Foreign host */
|
||||
#define so_faddr fhost.sin.sin_addr
|
||||
#define so_fport fhost.sin.sin_port
|
||||
#define so_faddr6 fhost.sin6.sin6_addr
|
||||
#define so_fport6 fhost.sin6.sin6_port
|
||||
#define so_ffamily fhost.ss.ss_family
|
||||
|
||||
uint8_t so_iptos; /* Type of service */
|
||||
uint8_t so_emu; /* Is the socket emulated? */
|
||||
union slirp_sockaddr lhost; /* Local host */
|
||||
#define so_laddr lhost.sin.sin_addr
|
||||
#define so_lport lhost.sin.sin_port
|
||||
#define so_laddr6 lhost.sin6.sin6_addr
|
||||
#define so_lport6 lhost.sin6.sin6_port
|
||||
#define so_lfamily lhost.ss.ss_family
|
||||
|
||||
u_char so_type; /* Type of socket, UDP or TCP */
|
||||
int so_state; /* internal state flags SS_*, below */
|
||||
uint8_t so_iptos; /* Type of service */
|
||||
uint8_t so_emu; /* Is the socket emulated? */
|
||||
|
||||
struct tcpcb *so_tcpcb; /* pointer to TCP protocol control block */
|
||||
u_int so_expire; /* When the socket will expire */
|
||||
uint8_t so_type; /* Protocol of the socket. May be 0 if loading old
|
||||
* states. */
|
||||
int32_t so_state; /* internal state flags SS_*, below */
|
||||
|
||||
int so_queued; /* Number of packets queued from this socket */
|
||||
int so_nqueued; /* Number of packets queued in a row
|
||||
* Used to determine when to "downgrade" a session
|
||||
* from fastq to batchq */
|
||||
struct tcpcb *so_tcpcb; /* pointer to TCP protocol control block */
|
||||
unsigned so_expire; /* When the socket will expire */
|
||||
|
||||
struct sbuf so_rcv; /* Receive buffer */
|
||||
struct sbuf so_snd; /* Send buffer */
|
||||
void * extra; /* Extra pointer */
|
||||
int so_queued; /* Number of packets queued from this socket */
|
||||
int so_nqueued; /* Number of packets queued in a row
|
||||
* Used to determine when to "downgrade" a session
|
||||
* from fastq to batchq */
|
||||
|
||||
struct sbuf so_rcv; /* Receive buffer */
|
||||
struct sbuf so_snd; /* Send buffer */
|
||||
};
|
||||
|
||||
|
||||
@ -62,21 +93,29 @@ struct socket {
|
||||
* Socket state bits. (peer means the host on the Internet,
|
||||
* local host means the host on the other end of the modem)
|
||||
*/
|
||||
#define SS_NOFDREF 0x001 /* No fd reference */
|
||||
#define SS_NOFDREF 0x001 /* No fd reference */
|
||||
|
||||
#define SS_ISFCONNECTING 0x002 /* Socket is connecting to peer (non-blocking connect()'s) */
|
||||
#define SS_ISFCONNECTED 0x004 /* Socket is connected to peer */
|
||||
#define SS_FCANTRCVMORE 0x008 /* Socket can't receive more from peer (for half-closes) */
|
||||
#define SS_FCANTSENDMORE 0x010 /* Socket can't send more to peer (for half-closes) */
|
||||
#define SS_FWDRAIN 0x040 /* We received a FIN, drain data and set SS_FCANTSENDMORE */
|
||||
#define SS_ISFCONNECTING \
|
||||
0x002 /* Socket is connecting to peer (non-blocking connect()'s) */
|
||||
#define SS_ISFCONNECTED 0x004 /* Socket is connected to peer */
|
||||
#define SS_FCANTRCVMORE \
|
||||
0x008 /* Socket can't receive more from peer (for half-closes) */
|
||||
#define SS_FCANTSENDMORE \
|
||||
0x010 /* Socket can't send more to peer (for half-closes) */
|
||||
#define SS_FWDRAIN \
|
||||
0x040 /* We received a FIN, drain data and set SS_FCANTSENDMORE */
|
||||
|
||||
#define SS_CTL 0x080
|
||||
#define SS_FACCEPTCONN 0x100 /* Socket is accepting connections from a host on the internet */
|
||||
#define SS_FACCEPTONCE 0x200 /* If set, the SS_FACCEPTCONN socket will die after one accept */
|
||||
#define SS_FACCEPTCONN \
|
||||
0x100 /* Socket is accepting connections from a host on the internet */
|
||||
#define SS_FACCEPTONCE \
|
||||
0x200 /* If set, the SS_FACCEPTCONN socket will die after one accept */
|
||||
|
||||
#define SS_PERSISTENT_MASK 0xf000 /* Unremovable state bits */
|
||||
#define SS_HOSTFWD 0x1000 /* Socket describes host->guest forwarding */
|
||||
#define SS_INCOMING 0x2000 /* Connection was initiated by a host on the internet */
|
||||
#define SS_PERSISTENT_MASK 0xf000 /* Unremovable state bits */
|
||||
#define SS_HOSTFWD 0x1000 /* Socket describes host->guest forwarding */
|
||||
#define SS_INCOMING \
|
||||
0x2000 /* Connection was initiated by a host on the internet */
|
||||
#define SS_HOSTFWD_V6ONLY 0x4000 /* Only bind on v6 addresses */
|
||||
|
||||
/* Check that two addresses are equal */
|
||||
static inline int sockaddr_equal(const struct sockaddr_storage *a,
|
||||
@ -132,22 +171,56 @@ static inline socklen_t sockaddr_size(const struct sockaddr_storage *a)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct socket * solookup(struct socket *, struct in_addr, u_int, struct in_addr, u_int);
|
||||
struct socket * socreate(Slirp *);
|
||||
/* Copy an address */
|
||||
static inline void sockaddr_copy(struct sockaddr *dst, socklen_t dstlen, const struct sockaddr *src, socklen_t srclen)
|
||||
{
|
||||
socklen_t len = sockaddr_size((const struct sockaddr_storage *) src);
|
||||
assert(len <= srclen);
|
||||
assert(len <= dstlen);
|
||||
memcpy(dst, src, len);
|
||||
}
|
||||
|
||||
/* Find the socket corresponding to lhost & fhost, trying last as a guess */
|
||||
struct socket *solookup(struct socket *, struct in_addr, u_int, struct in_addr, u_int);
|
||||
/* Create a new socket */
|
||||
struct socket *socreate(Slirp *);
|
||||
/* Release a socket */
|
||||
void sofree(struct socket *);
|
||||
/* Receive the available data from the Internet socket and queue it on the sb */
|
||||
int soread(struct socket *);
|
||||
/* Receive the available OOB data from the Internet socket and try to send it immediately */
|
||||
int sorecvoob(struct socket *);
|
||||
/* Send OOB data to the Internet socket */
|
||||
int sosendoob(struct socket *);
|
||||
/* Send data to the Internet socket */
|
||||
int sowrite(struct socket *);
|
||||
/* Receive the available data from the Internet UDP socket, and send it to the guest */
|
||||
void sorecvfrom(struct socket *);
|
||||
/* Send data to the Internet UDP socket */
|
||||
int sosendto(struct socket *, struct mbuf *);
|
||||
struct socket * tcp_listen(Slirp *, uint32_t, u_int, uint32_t, u_int,
|
||||
int);
|
||||
/* Listen for incoming TCPv4 connections on this haddr+hport */
|
||||
struct socket * tcp_listen(Slirp *, uint32_t haddr, unsigned hport, uint32_t laddr, unsigned lport, int flags);
|
||||
/*
|
||||
* Listen for incoming TCP connections on this haddr
|
||||
* On failure errno contains the reason.
|
||||
*/
|
||||
struct socket * tcpx_listen(Slirp *slirp,
|
||||
const struct sockaddr *haddr, socklen_t haddrlen,
|
||||
const struct sockaddr *laddr, socklen_t laddrlen,
|
||||
int flags);
|
||||
/* Note that the socket is connecting */
|
||||
void soisfconnecting(struct socket *);
|
||||
/* Note that the socket is connected */
|
||||
void soisfconnected(struct socket *);
|
||||
/*
|
||||
* Set write drain mode
|
||||
* Set CANTSENDMORE once all data has been write()n
|
||||
*/
|
||||
void sofwdrain(struct socket *);
|
||||
struct iovec; /* For win32 */
|
||||
/* Prepare iov for storing into the sb */
|
||||
size_t sopreprbuf(struct socket *so, struct iovec *iov, int *np);
|
||||
/* Get data from the buffer and queue it on the sb */
|
||||
int soreadbuf(struct socket *so, const char *buf, int size);
|
||||
|
||||
#endif /* SLIRP_SOCKET_H */
|
||||
|
@ -36,11 +36,12 @@
|
||||
|
||||
typedef uint32_t tcp_seq;
|
||||
|
||||
#define PR_SLOWHZ 2 /* 2 slow timeouts per second (approx) */
|
||||
#define PR_FASTHZ 5 /* 5 fast timeouts per second (not important) */
|
||||
#define PR_SLOWHZ 2 /* 2 slow timeouts per second (approx) */
|
||||
#define PR_FASTHZ 5 /* 5 fast timeouts per second (not important) */
|
||||
|
||||
#define TCP_SNDSPACE 8192
|
||||
#define TCP_RCVSPACE 8192
|
||||
#define TCP_SNDSPACE 1024 * 128
|
||||
#define TCP_RCVSPACE 1024 * 128
|
||||
#define TCP_MAXSEG_MAX 32768
|
||||
|
||||
/*
|
||||
* TCP header.
|
||||
|
@ -526,7 +526,7 @@ findso:
|
||||
win = sbspace(&so->so_rcv);
|
||||
if (win < 0)
|
||||
win = 0;
|
||||
tp->rcv_wnd = max(win, (int)(tp->rcv_adv - tp->rcv_nxt));
|
||||
tp->rcv_wnd = MAX(win, (int)(tp->rcv_adv - tp->rcv_nxt));
|
||||
}
|
||||
|
||||
switch (tp->t_state) {
|
||||
@ -952,7 +952,7 @@ trimthenstep6:
|
||||
else if (++tp->t_dupacks == TCPREXMTTHRESH) {
|
||||
tcp_seq onxt = tp->snd_nxt;
|
||||
u_int win =
|
||||
min(tp->snd_wnd, tp->snd_cwnd) / 2 /
|
||||
MIN(tp->snd_wnd, tp->snd_cwnd) / 2 /
|
||||
tp->t_maxseg;
|
||||
|
||||
if (win < 2)
|
||||
@ -1025,7 +1025,7 @@ trimthenstep6:
|
||||
|
||||
if (cw > tp->snd_ssthresh)
|
||||
incr = incr * incr / cw;
|
||||
tp->snd_cwnd = min((int)(cw + incr), TCP_MAXWIN<<tp->snd_scale);
|
||||
tp->snd_cwnd = MIN((int)(cw + incr), TCP_MAXWIN<<tp->snd_scale);
|
||||
}
|
||||
if (acked > (int)so->so_snd.sb_cc) {
|
||||
tp->snd_wnd -= so->so_snd.sb_cc;
|
||||
@ -1471,10 +1471,11 @@ tcp_mss(struct tcpcb *tp, u_int offer)
|
||||
DEBUG_ARG("tp = %lx", (long)tp);
|
||||
DEBUG_ARG("offer = %d", offer);
|
||||
|
||||
mss = min(IF_MTU_DEFAULT, IF_MRU_DEFAULT) - sizeof(struct tcpiphdr);
|
||||
mss = MIN(so->slirp->if_mtu, so->slirp->if_mru) -
|
||||
sizeof(struct tcphdr) - sizeof(struct ip);
|
||||
if (offer)
|
||||
mss = min(mss, (int)offer);
|
||||
mss = max(mss, 32);
|
||||
mss = MIN(mss, (int)offer);
|
||||
mss = MAX(mss, 32);
|
||||
if (mss < tp->t_maxseg || offer != 0)
|
||||
tp->t_maxseg = mss;
|
||||
|
||||
|
@ -88,7 +88,7 @@ tcp_output(struct tcpcb *tp)
|
||||
again:
|
||||
sendalot = 0;
|
||||
off = tp->snd_nxt - tp->snd_una;
|
||||
win = min(tp->snd_wnd, tp->snd_cwnd);
|
||||
win = MIN(tp->snd_wnd, tp->snd_cwnd);
|
||||
|
||||
flags = tcp_outflags[tp->t_state];
|
||||
|
||||
@ -127,7 +127,7 @@ again:
|
||||
}
|
||||
}
|
||||
|
||||
len = min((long)so->so_snd.sb_cc, win) - off;
|
||||
len = MIN((long)so->so_snd.sb_cc, win) - off;
|
||||
|
||||
if (len < 0) {
|
||||
/*
|
||||
@ -193,7 +193,7 @@ again:
|
||||
* taking into account that we are limited by
|
||||
* TCP_MAXWIN << tp->rcv_scale.
|
||||
*/
|
||||
long adv = min(win, (long)TCP_MAXWIN << tp->rcv_scale) -
|
||||
long adv = MIN(win, (long)TCP_MAXWIN << tp->rcv_scale) -
|
||||
(tp->rcv_adv - tp->rcv_nxt);
|
||||
|
||||
if (adv >= (long) (2 * tp->t_maxseg))
|
||||
|
@ -181,21 +181,26 @@ tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m,
|
||||
* empty reassembly queue and hooking it to the argument
|
||||
* protocol control block.
|
||||
*/
|
||||
struct tcpcb *
|
||||
tcp_newtcpcb(struct socket *so)
|
||||
struct tcpcb *tcp_newtcpcb(struct socket *so)
|
||||
{
|
||||
struct tcpcb *tp;
|
||||
struct tcpcb *tp;
|
||||
|
||||
tp = (struct tcpcb *)malloc(sizeof(*tp));
|
||||
if (tp == NULL)
|
||||
return ((struct tcpcb *)0);
|
||||
tp = (struct tcpcb *)malloc(sizeof(*tp));
|
||||
if (tp == NULL)
|
||||
return ((struct tcpcb *)0);
|
||||
|
||||
memset((char *) tp, 0, sizeof(struct tcpcb));
|
||||
tp->seg_next = tp->seg_prev = (struct tcpiphdr*)tp;
|
||||
tp->t_maxseg = TCP_MSS;
|
||||
memset((char *) tp, 0, sizeof(struct tcpcb));
|
||||
tp->seg_next = tp->seg_prev = (struct tcpiphdr*)tp;
|
||||
/*
|
||||
* 40: length of IPv4 header (20) + TCP header (20)
|
||||
* 60: length of IPv6 header (40) + TCP header (20)
|
||||
*/
|
||||
tp->t_maxseg =
|
||||
MIN(so->slirp->if_mtu - 40,
|
||||
TCP_MAXSEG_MAX);
|
||||
|
||||
tp->t_flags = TCP_DO_RFC1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
|
||||
tp->t_socket = so;
|
||||
tp->t_flags = TCP_DO_RFC1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
|
||||
tp->t_socket = so;
|
||||
|
||||
/*
|
||||
* Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no
|
||||
@ -900,7 +905,6 @@ int tcp_ctl(struct socket *so)
|
||||
Slirp *slirp = so->slirp;
|
||||
struct sbuf *sb = &so->so_snd;
|
||||
struct gfwd_list *ex_ptr;
|
||||
int do_pty;
|
||||
|
||||
DEBUG_CALL("tcp_ctl");
|
||||
DEBUG_ARG("so = %lx", (long )so);
|
||||
@ -910,16 +914,16 @@ 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_pty == 3) {
|
||||
if (ex_ptr->write_cb) {
|
||||
so->s = -1;
|
||||
so->extra = (void *)ex_ptr->ex_exec;
|
||||
so->guestfwd = ex_ptr;
|
||||
return 1;
|
||||
}
|
||||
do_pty = ex_ptr->ex_pty;
|
||||
*/
|
||||
DEBUG_MISC((dfd, " executing %s\n", ex_ptr->ex_exec));
|
||||
return fork_exec(so, ex_ptr->ex_exec, do_pty);
|
||||
DEBUG_MISC((dfd, " executing %s", ex_ptr->ex_exec));
|
||||
if (ex_ptr->ex_unix)
|
||||
return open_unix(so, ex_ptr->ex_unix);
|
||||
else
|
||||
return fork_exec(so, ex_ptr->ex_exec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -235,7 +235,7 @@ tcp_timers(struct tcpcb *tp, int timer)
|
||||
* to go below this.)
|
||||
*/
|
||||
{
|
||||
u_int win = min(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg;
|
||||
u_int win = MIN(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg;
|
||||
if (win < 2)
|
||||
win = 2;
|
||||
tp->snd_cwnd = tp->t_maxseg;
|
||||
|
Loading…
Reference in New Issue
Block a user