Some work on the builtin slirp support
- fixed Windows netmod plugin - reduce differences to latest Qemu sources (to be continued)
This commit is contained in:
parent
ec4b7d717e
commit
8f3695aedf
@ -115,7 +115,7 @@ bx_%.dll: %.o
|
||||
|
||||
# special link rules for plugins that require more than one object file
|
||||
bx_netmod.dll: netmod.o $(NETLOW_OBJS)
|
||||
$(CXX) $(CXXFLAGS) -shared -o bx_netmod.dll netmod.o $(NETLOW_OBJS) $(WIN32_DLL_IMPORT_LIBRARY) -lws2_32
|
||||
$(CXX) $(CXXFLAGS) -shared -o bx_netmod.dll netmod.o $(NETLOW_OBJS) $(WIN32_DLL_IMPORT_LIBRARY) -lws2_32 -liphlpapi
|
||||
|
||||
##### end DLL section
|
||||
|
||||
|
@ -38,7 +38,9 @@ void arp_table_add(Slirp *slirp, uint32_t ip_addr, uint8_t ethaddr[ETH_ALEN])
|
||||
ethaddr[3], ethaddr[4], ethaddr[5]));
|
||||
|
||||
/* Check 0.0.0.0/8 invalid source-only addresses */
|
||||
assert((ip_addr & htonl(~(0xf << 28))) != 0);
|
||||
if ((ip_addr & htonl(~(0xfU << 28))) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ip_addr == 0xffffffff || ip_addr == broadcast_addr) {
|
||||
/* Do not register broadcast addresses */
|
||||
@ -72,7 +74,7 @@ bool arp_table_search(Slirp *slirp, uint32_t ip_addr,
|
||||
DEBUG_ARG("ip = 0x%x", ip_addr);
|
||||
|
||||
/* Check 0.0.0.0/8 invalid source-only addresses */
|
||||
assert((ip_addr & htonl(~(0xf << 28))) != 0);
|
||||
assert((ip_addr & htonl(~(0xfU << 28))) != 0);
|
||||
|
||||
/* If broadcast address */
|
||||
if (ip_addr == 0xffffffff || ip_addr == broadcast_addr) {
|
||||
|
@ -1,4 +1,6 @@
|
||||
/* bootp/dhcp defines */
|
||||
#ifndef SLIRP_BOOTP_H
|
||||
#define SLIRP_BOOTP_H 1
|
||||
|
||||
#define BOOTP_SERVER 67
|
||||
#define BOOTP_CLIENT 68
|
||||
@ -120,3 +122,5 @@ typedef struct {
|
||||
#define NB_BOOTP_CLIENTS 16
|
||||
|
||||
void bootp_input(struct mbuf *m);
|
||||
|
||||
#endif
|
||||
|
@ -75,7 +75,7 @@ int cksum(struct mbuf *m, int len)
|
||||
/*
|
||||
* Force to even boundary.
|
||||
*/
|
||||
if ((1 & (uintptr_t) w) && (mlen > 0)) {
|
||||
if ((1 & (uintptr_t)w) && (mlen > 0)) {
|
||||
REDUCE;
|
||||
sum <<= 8;
|
||||
s_util.c[0] = *(uint8_t *)w;
|
||||
|
@ -41,7 +41,7 @@ void pstrcpy(char *buf, int buf_size, const char *str)
|
||||
*q = '\0';
|
||||
}
|
||||
|
||||
void socket_set_nonblock(int fd)
|
||||
void qemu_set_nonblock(int fd)
|
||||
{
|
||||
#ifdef WIN32
|
||||
unsigned long opt = 1;
|
||||
|
@ -121,8 +121,11 @@ struct iovec {
|
||||
void pstrcpy(char *buf, int buf_size, const char *str);
|
||||
int qemu_socket(int domain, int type, int protocol);
|
||||
#ifdef WIN32
|
||||
#define qemu_recv(a,b,c,d) recv(a,(char*)b,c,d)
|
||||
int inet_aton(const char *cp, struct in_addr *ia);
|
||||
#else
|
||||
#define qemu_recv(a,b,c,d) recv(a,b,c,d)
|
||||
#endif
|
||||
void socket_set_nonblock(int fd);
|
||||
void qemu_set_nonblock(int fd);
|
||||
|
||||
#endif
|
||||
|
@ -142,7 +142,7 @@ diddit:
|
||||
|
||||
/*
|
||||
* Send a packet
|
||||
* We choose a packet based on it's position in the output queues;
|
||||
* We choose a packet based on its position in the output queues;
|
||||
* If there are packets on the fastq, they are sent FIFO, before
|
||||
* everything else. Otherwise we choose the first packet from the
|
||||
* batchq and send it. the next packet chosen will be from the session
|
||||
|
@ -352,7 +352,7 @@ icmp_error(struct mbuf *msrc, u_char type, u_char code, int minsize,
|
||||
|
||||
ip->ip_ttl = MAXTTL;
|
||||
ip->ip_p = IPPROTO_ICMP;
|
||||
ip->ip_dst = ip->ip_src; /* ip adresses */
|
||||
ip->ip_dst = ip->ip_src; /* ip addresses */
|
||||
ip->ip_src = m->slirp->vhost_addr;
|
||||
|
||||
(void ) ip_output((struct socket *)NULL, m);
|
||||
@ -427,7 +427,7 @@ void icmp_receive(struct socket *so)
|
||||
icp = mtod(m, struct icmp *);
|
||||
|
||||
id = icp->icmp_id;
|
||||
len = recv(so->s, (char*)icp, m->m_len, 0);
|
||||
len = qemu_recv(so->s, icp, m->m_len, 0);
|
||||
icp->icmp_id = id;
|
||||
|
||||
m->m_data -= hlen;
|
||||
|
@ -92,8 +92,8 @@ struct icmp {
|
||||
|
||||
/*
|
||||
* Lower bounds on packet lengths for various types.
|
||||
* For the error advice packets must first insure that the
|
||||
* packet is large enought to contain the returned ip header.
|
||||
* For the error advice packets must first ensure that the
|
||||
* packet is large enough to contain the returned ip header.
|
||||
* Only then can we do the check to see if 64 bits of packet
|
||||
* data have been returned, since we need to check the returned
|
||||
* ip header length.
|
||||
|
@ -4,6 +4,8 @@
|
||||
* Please read the file COPYRIGHT for the
|
||||
* terms and conditions of the copyright.
|
||||
*/
|
||||
#ifndef SLIRP_MAIN_H
|
||||
#define SLIRP_MAIN_H 1
|
||||
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h>
|
||||
@ -44,3 +46,5 @@ extern int tcp_keepintvl;
|
||||
|
||||
int if_encap(Slirp *slirp, struct mbuf *ifm);
|
||||
ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags);
|
||||
|
||||
#endif
|
||||
|
@ -215,7 +215,7 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
|
||||
setsockopt(so->s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(int));
|
||||
opt = 1;
|
||||
setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, (char *)&opt, sizeof(int));
|
||||
socket_set_nonblock(so->s);
|
||||
qemu_set_nonblock(so->s);
|
||||
|
||||
/* Append the telnet options now */
|
||||
if (so->so_m != NULL && do_pty == 1) {
|
||||
|
@ -528,7 +528,7 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
|
||||
*/
|
||||
#ifdef PROBE_CONN
|
||||
if (so->so_state & SS_ISFCONNECTING) {
|
||||
ret = recv(so->s, (char *)&ret, 0,0);
|
||||
ret = qemu_recv(so->s, &ret, 0, 0);
|
||||
|
||||
if (ret < 0) {
|
||||
/* XXX */
|
||||
@ -818,12 +818,12 @@ int slirp_add_exec(Slirp *slirp, int do_pty, const void *args,
|
||||
|
||||
ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)
|
||||
{
|
||||
if (so->s == -1 && so->extra) {
|
||||
BX_ERROR(("slirp_send(): so->extra not supported"));
|
||||
return len;
|
||||
}
|
||||
if (so->s == -1 && so->extra) {
|
||||
BX_ERROR(("slirp_send(): so->extra not supported"));
|
||||
return len;
|
||||
}
|
||||
|
||||
return send(so->s, (const char*)buf, len, flags);
|
||||
return send(so->s, (const char*)buf, len, flags);
|
||||
}
|
||||
|
||||
static struct socket *
|
||||
@ -843,18 +843,20 @@ slirp_find_ctl_socket(Slirp *slirp, struct in_addr guest_addr, int guest_port)
|
||||
size_t slirp_socket_can_recv(Slirp *slirp, struct in_addr guest_addr,
|
||||
int guest_port)
|
||||
{
|
||||
struct iovec iov[2];
|
||||
struct socket *so;
|
||||
struct iovec iov[2];
|
||||
struct socket *so;
|
||||
|
||||
so = slirp_find_ctl_socket(slirp, guest_addr, guest_port);
|
||||
so = slirp_find_ctl_socket(slirp, guest_addr, guest_port);
|
||||
|
||||
if (!so || so->so_state & SS_NOFDREF)
|
||||
return 0;
|
||||
if (!so || so->so_state & SS_NOFDREF) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!CONN_CANFRCV(so) || so->so_snd.sb_cc >= (so->so_snd.sb_datalen/2))
|
||||
return 0;
|
||||
if (!CONN_CANFRCV(so) || so->so_snd.sb_cc >= (so->so_snd.sb_datalen/2)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return sopreprbuf(so, iov, NULL);
|
||||
return sopreprbuf(so, iov, NULL);
|
||||
}
|
||||
|
||||
void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr, int guest_port,
|
||||
|
@ -165,7 +165,7 @@ soread(struct socket *so)
|
||||
nn = readv(so->s, (struct iovec *)iov, n);
|
||||
DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
|
||||
#else
|
||||
nn = recv(so->s, (char*)iov[0].iov_base, iov[0].iov_len,0);
|
||||
nn = qemu_recv(so->s, iov[0].iov_base, iov[0].iov_len,0);
|
||||
#endif
|
||||
if (nn <= 0) {
|
||||
if (nn < 0 && (errno == EINTR || errno == EAGAIN))
|
||||
@ -190,7 +190,7 @@ soread(struct socket *so)
|
||||
*/
|
||||
if (n == 2 && nn == (int)iov[0].iov_len) {
|
||||
int ret;
|
||||
ret = recv(so->s, (char*)iov[1].iov_base, iov[1].iov_len,0);
|
||||
ret = qemu_recv(so->s, iov[1].iov_base, iov[1].iov_len,0);
|
||||
if (ret > 0)
|
||||
nn += ret;
|
||||
}
|
||||
|
@ -316,16 +316,6 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
|
||||
m->m_data += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
|
||||
m->m_len -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
|
||||
|
||||
if (slirp->restricted) {
|
||||
for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
|
||||
if (ex_ptr->ex_fport == ti->ti_dport &&
|
||||
ti->ti_dst.s_addr == ex_ptr->ex_addr.s_addr) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ex_ptr)
|
||||
goto drop;
|
||||
}
|
||||
/*
|
||||
* Locate pcb for segment.
|
||||
*/
|
||||
@ -355,6 +345,22 @@ findso:
|
||||
* as if it was LISTENING, and continue...
|
||||
*/
|
||||
if (so == NULL) {
|
||||
if (slirp->restricted) {
|
||||
/* Any hostfwds will have an existing socket, so we only get here
|
||||
* for non-hostfwd connections. These should be dropped, unless it
|
||||
* happens to be a guestfwd.
|
||||
*/
|
||||
for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
|
||||
if (ex_ptr->ex_fport == ti->ti_dport &&
|
||||
ti->ti_dst.s_addr == ex_ptr->ex_addr.s_addr) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ex_ptr) {
|
||||
goto dropwithreset;
|
||||
}
|
||||
}
|
||||
|
||||
if ((tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) != TH_SYN)
|
||||
goto dropwithreset;
|
||||
|
||||
@ -1281,8 +1287,6 @@ drop:
|
||||
* Drop space held by incoming segment and return.
|
||||
*/
|
||||
m_free(m);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -114,9 +114,9 @@ tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m,
|
||||
int win = 0;
|
||||
|
||||
DEBUG_CALL("tcp_respond");
|
||||
DEBUG_ARG("tp = %lx", (long)tp);
|
||||
DEBUG_ARG("ti = %lx", (long)ti);
|
||||
DEBUG_ARG("m = %lx", (long)m);
|
||||
DEBUG_ARG("tp = %p", tp);
|
||||
DEBUG_ARG("ti = %p", ti);
|
||||
DEBUG_ARG("m = %p", m);
|
||||
DEBUG_ARG("ack = %u", ack);
|
||||
DEBUG_ARG("seq = %u", seq);
|
||||
DEBUG_ARG("flags = %x", flags);
|
||||
@ -124,7 +124,7 @@ tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m,
|
||||
if (tp)
|
||||
win = sbspace(&tp->t_socket->so_rcv);
|
||||
if (m == NULL) {
|
||||
if ((m = m_get(tp->t_socket->slirp)) == NULL)
|
||||
if (!tp || (m = m_get(tp->t_socket->slirp)) == NULL)
|
||||
return;
|
||||
tlen = 0;
|
||||
m->m_data += IF_MAXLINKHDR;
|
||||
@ -336,7 +336,7 @@ int tcp_fconnect(struct socket *so)
|
||||
int opt, s=so->s;
|
||||
struct sockaddr_in addr;
|
||||
|
||||
socket_set_nonblock(s);
|
||||
qemu_set_nonblock(s);
|
||||
opt = 1;
|
||||
setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(opt ));
|
||||
opt = 1;
|
||||
@ -384,80 +384,81 @@ int tcp_fconnect(struct socket *so)
|
||||
* the time it gets to accept(), so... We simply accept
|
||||
* here and SYN the local-host.
|
||||
*/
|
||||
void
|
||||
tcp_connect(struct socket *inso)
|
||||
void tcp_connect(struct socket *inso)
|
||||
{
|
||||
Slirp *slirp = inso->slirp;
|
||||
struct socket *so;
|
||||
struct sockaddr_in addr;
|
||||
socklen_t addrlen = sizeof(struct sockaddr_in);
|
||||
struct tcpcb *tp;
|
||||
int s, opt;
|
||||
Slirp *slirp = inso->slirp;
|
||||
struct socket *so;
|
||||
struct sockaddr_in addr;
|
||||
socklen_t addrlen = sizeof(struct sockaddr_in);
|
||||
struct tcpcb *tp;
|
||||
int s, opt;
|
||||
|
||||
DEBUG_CALL("tcp_connect");
|
||||
DEBUG_ARG("inso = %lx", (long)inso);
|
||||
DEBUG_CALL("tcp_connect");
|
||||
DEBUG_ARG("inso = %lx", (long)inso);
|
||||
|
||||
/*
|
||||
* If it's an SS_ACCEPTONCE socket, no need to socreate()
|
||||
* another socket, just use the accept() socket.
|
||||
*/
|
||||
if (inso->so_state & SS_FACCEPTONCE) {
|
||||
/* FACCEPTONCE already have a tcpcb */
|
||||
so = inso;
|
||||
} else {
|
||||
if ((so = socreate(slirp)) == NULL) {
|
||||
/* If it failed, get rid of the pending connection */
|
||||
closesocket(accept(inso->s,(struct sockaddr *)&addr,&addrlen));
|
||||
return;
|
||||
}
|
||||
if (tcp_attach(so) < 0) {
|
||||
free(so); /* NOT sofree */
|
||||
return;
|
||||
}
|
||||
so->so_laddr = inso->so_laddr;
|
||||
so->so_lport = inso->so_lport;
|
||||
}
|
||||
/*
|
||||
* If it's an SS_ACCEPTONCE socket, no need to socreate()
|
||||
* another socket, just use the accept() socket.
|
||||
*/
|
||||
if (inso->so_state & SS_FACCEPTONCE) {
|
||||
/* FACCEPTONCE already have a tcpcb */
|
||||
so = inso;
|
||||
} else {
|
||||
so = socreate(slirp);
|
||||
if (so == NULL) {
|
||||
/* If it failed, get rid of the pending connection */
|
||||
closesocket(accept(inso->s, (struct sockaddr *)&addr, &addrlen));
|
||||
return;
|
||||
}
|
||||
if (tcp_attach(so) < 0) {
|
||||
free(so); /* NOT sofree */
|
||||
return;
|
||||
}
|
||||
so->so_laddr = inso->so_laddr;
|
||||
so->so_lport = inso->so_lport;
|
||||
}
|
||||
|
||||
(void) tcp_mss(sototcpcb(so), 0);
|
||||
tcp_mss(sototcpcb(so), 0);
|
||||
|
||||
if ((s = accept(inso->s,(struct sockaddr *)&addr,&addrlen)) < 0) {
|
||||
tcp_close(sototcpcb(so)); /* This will sofree() as well */
|
||||
return;
|
||||
}
|
||||
socket_set_nonblock(s);
|
||||
opt = 1;
|
||||
setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
|
||||
opt = 1;
|
||||
setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
|
||||
opt = 1;
|
||||
setsockopt(s,IPPROTO_TCP,TCP_NODELAY,(char *)&opt,sizeof(int));
|
||||
s = accept(inso->s, (struct sockaddr *)&addr, &addrlen);
|
||||
if (s < 0) {
|
||||
tcp_close(sototcpcb(so)); /* This will sofree() as well */
|
||||
return;
|
||||
}
|
||||
qemu_set_nonblock(s);
|
||||
opt = 1;
|
||||
setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
|
||||
opt = 1;
|
||||
setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
|
||||
opt = 1;
|
||||
setsockopt(s,IPPROTO_TCP,TCP_NODELAY,(char *)&opt,sizeof(int));
|
||||
|
||||
so->so_fport = addr.sin_port;
|
||||
so->so_faddr = addr.sin_addr;
|
||||
/* Translate connections from localhost to the real hostname */
|
||||
if (so->so_faddr.s_addr == 0 || so->so_faddr.s_addr == loopback_addr.s_addr)
|
||||
so->so_faddr = slirp->vhost_addr;
|
||||
so->so_fport = addr.sin_port;
|
||||
so->so_faddr = addr.sin_addr;
|
||||
/* Translate connections from localhost to the real hostname */
|
||||
if (so->so_faddr.s_addr == 0 || so->so_faddr.s_addr == loopback_addr.s_addr)
|
||||
so->so_faddr = slirp->vhost_addr;
|
||||
|
||||
/* Close the accept() socket, set right state */
|
||||
if (inso->so_state & SS_FACCEPTONCE) {
|
||||
closesocket(so->s); /* If we only accept once, close the accept() socket */
|
||||
so->so_state = SS_NOFDREF; /* Don't select it yet, even though we have an FD */
|
||||
/* if it's not FACCEPTONCE, it's already NOFDREF */
|
||||
}
|
||||
so->s = s;
|
||||
so->so_state |= SS_INCOMING;
|
||||
/* Close the accept() socket, set right state */
|
||||
if (inso->so_state & SS_FACCEPTONCE) {
|
||||
closesocket(so->s); /* If we only accept once, close the accept() socket */
|
||||
so->so_state = SS_NOFDREF; /* Don't select it yet, even though we have an FD */
|
||||
/* if it's not FACCEPTONCE, it's already NOFDREF */
|
||||
}
|
||||
so->s = s;
|
||||
so->so_state |= SS_INCOMING;
|
||||
|
||||
so->so_iptos = tcp_tos(so);
|
||||
tp = sototcpcb(so);
|
||||
so->so_iptos = tcp_tos(so);
|
||||
tp = sototcpcb(so);
|
||||
|
||||
tcp_template(tp);
|
||||
tcp_template(tp);
|
||||
|
||||
tp->t_state = TCPS_SYN_SENT;
|
||||
tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
|
||||
tp->iss = slirp->tcp_iss;
|
||||
slirp->tcp_iss += TCP_ISSINCR/2;
|
||||
tcp_sendseqinit(tp);
|
||||
tcp_output(tp);
|
||||
tp->t_state = TCPS_SYN_SENT;
|
||||
tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
|
||||
tp->iss = slirp->tcp_iss;
|
||||
slirp->tcp_iss += TCP_ISSINCR/2;
|
||||
tcp_sendseqinit(tp);
|
||||
tcp_output(tp);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -231,7 +231,6 @@ udp_input(register struct mbuf *m, int iphlen)
|
||||
return;
|
||||
bad:
|
||||
m_free(m);
|
||||
return;
|
||||
}
|
||||
|
||||
int udp_output2(struct socket *so, struct mbuf *m,
|
||||
|
Loading…
Reference in New Issue
Block a user