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:
Volker Ruppert 2014-02-16 20:35:28 +00:00
parent ec4b7d717e
commit 8f3695aedf
16 changed files with 129 additions and 110 deletions

View File

@ -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

View File

@ -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) {

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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.

View File

@ -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

View File

@ -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) {

View File

@ -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,

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}
/*

View File

@ -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,