From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LL0Oh-0006ZS-Tk for qemu-devel@nongnu.org; Thu, 08 Jan 2009 14:18:28 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LL0Oh-0006Yx-1k for qemu-devel@nongnu.org; Thu, 08 Jan 2009 14:18:27 -0500 Received: from [199.232.76.173] (port=59290 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LL0Og-0006Yn-QN for qemu-devel@nongnu.org; Thu, 08 Jan 2009 14:18:26 -0500 Received: from savannah.gnu.org ([199.232.41.3]:47903 helo=sv.gnu.org) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1LL0Og-0002Pv-Gk for qemu-devel@nongnu.org; Thu, 08 Jan 2009 14:18:26 -0500 Received: from cvs.savannah.gnu.org ([199.232.41.69]) by sv.gnu.org with esmtp (Exim 4.63) (envelope-from ) id 1LL0Oe-0005wa-MI for qemu-devel@nongnu.org; Thu, 08 Jan 2009 19:18:25 +0000 Received: from aliguori by cvs.savannah.gnu.org with local (Exim 4.63) (envelope-from ) id 1LL0Od-0005wS-HO for qemu-devel@nongnu.org; Thu, 08 Jan 2009 19:18:23 +0000 MIME-Version: 1.0 Errors-To: aliguori Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Anthony Liguori Message-Id: Date: Thu, 08 Jan 2009 19:18:23 +0000 Subject: [Qemu-devel] [6240] Redirect slirp traffic to/from qemu character device (Gleb Natapov) Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Revision: 6240 http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=6240 Author: aliguori Date: 2009-01-08 19:18:21 +0000 (Thu, 08 Jan 2009) Log Message: ----------- Redirect slirp traffic to/from qemu character device (Gleb Natapov) Signed-off-by: Gleb Natapov Signed-off-by: Anthony Liguori Modified Paths: -------------- trunk/slirp/libslirp.h trunk/slirp/main.h trunk/slirp/misc.c trunk/slirp/sbuf.c trunk/slirp/slirp.c trunk/slirp/socket.c trunk/slirp/socket.h trunk/slirp/tcp_subr.c Modified: trunk/slirp/libslirp.h =================================================================== --- trunk/slirp/libslirp.h 2009-01-08 19:01:37 UTC (rev 6239) +++ trunk/slirp/libslirp.h 2009-01-08 19:18:21 UTC (rev 6240) @@ -20,13 +20,16 @@ int slirp_redir(int is_udp, int host_port, struct in_addr guest_addr, int guest_port); -int slirp_add_exec(int do_pty, const char *args, int addr_low_byte, +int slirp_add_exec(int do_pty, const void *args, int addr_low_byte, int guest_port); extern const char *tftp_prefix; extern char slirp_hostname[33]; void slirp_stats(void); +void slirp_socket_recv(int addr_low_byte, int guest_port, const uint8_t *buf, + int size); +size_t slirp_socket_can_recv(int addr_low_byte, int guest_port); #ifdef __cplusplus } Modified: trunk/slirp/main.h =================================================================== --- trunk/slirp/main.h 2009-01-08 19:01:37 UTC (rev 6239) +++ trunk/slirp/main.h 2009-01-08 19:18:21 UTC (rev 6240) @@ -51,3 +51,4 @@ #endif void if_encap(const uint8_t *ip_data, int ip_data_len); +ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags); Modified: trunk/slirp/misc.c =================================================================== --- trunk/slirp/misc.c 2009-01-08 19:01:37 UTC (rev 6239) +++ trunk/slirp/misc.c 2009-01-08 19:18:21 UTC (rev 6240) @@ -169,7 +169,7 @@ (*ex_ptr)->ex_fport = port; (*ex_ptr)->ex_addr = addr; (*ex_ptr)->ex_pty = do_pty; - (*ex_ptr)->ex_exec = strdup(exec); + (*ex_ptr)->ex_exec = (do_pty == 3) ? exec : strdup(exec); (*ex_ptr)->ex_next = tmp_ptr; return 0; } Modified: trunk/slirp/sbuf.c =================================================================== --- trunk/slirp/sbuf.c 2009-01-08 19:01:37 UTC (rev 6239) +++ trunk/slirp/sbuf.c 2009-01-08 19:18:21 UTC (rev 6240) @@ -108,7 +108,7 @@ * ottherwise it'll arrive out of order, and hence corrupt */ if (!so->so_rcv.sb_cc) - ret = send(so->s, m->m_data, m->m_len, 0); + ret = slirp_send(so, m->m_data, m->m_len, 0); if (ret <= 0) { /* Modified: trunk/slirp/slirp.c =================================================================== --- trunk/slirp/slirp.c 2009-01-08 19:01:37 UTC (rev 6239) +++ trunk/slirp/slirp.c 2009-01-08 19:18:21 UTC (rev 6240) @@ -21,6 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#include "qemu-common.h" #include "slirp.h" /* host address */ @@ -736,9 +737,69 @@ return 0; } -int slirp_add_exec(int do_pty, const char *args, int addr_low_byte, +int slirp_add_exec(int do_pty, const void *args, int addr_low_byte, int guest_port) { return add_exec(&exec_list, do_pty, (char *)args, addr_low_byte, htons(guest_port)); } + +ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags) +{ + if (so->s == -1 && so->extra) { + qemu_chr_write(so->extra, buf, len); + return len; + } + + return send(so->s, buf, len, flags); +} + +static struct socket *slirp_find_ctl_socket(int addr_low_byte, int guest_port) +{ + struct socket *so; + + for (so = tcb.so_next; so != &tcb; so = so->so_next) { + if ((so->so_faddr.s_addr & htonl(0xffffff00)) == + special_addr.s_addr + && (ntohl(so->so_faddr.s_addr) & 0xff) == + addr_low_byte + && htons(so->so_fport) == guest_port) + return so; + } + + return NULL; +} + +size_t slirp_socket_can_recv(int addr_low_byte, int guest_port) +{ + struct iovec iov[2]; + struct socket *so; + + if (!link_up) + return 0; + + so = slirp_find_ctl_socket(addr_low_byte, guest_port); + + 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; + + return sopreprbuf(so, iov, NULL); +} + +void slirp_socket_recv(int addr_low_byte, int guest_port, const uint8_t *buf, + int size) +{ + int ret; + struct socket *so = slirp_find_ctl_socket(addr_low_byte, guest_port); + + if (!so) + return; + + ret = soreadbuf(so, buf, size); + + if (ret > 0) + tcp_output(sototcpcb(so)); +} Modified: trunk/slirp/socket.c =================================================================== --- trunk/slirp/socket.c 2009-01-08 19:01:37 UTC (rev 6239) +++ trunk/slirp/socket.c 2009-01-08 19:18:21 UTC (rev 6240) @@ -5,13 +5,13 @@ * terms and conditions of the copyright. */ +#include "qemu-common.h" #define WANT_SYS_IOCTL_H #include #include "ip_icmp.h" #ifdef __sun__ #include #endif -#include "qemu-common.h" static void sofcantrcvmore(struct socket *so); static void sofcantsendmore(struct socket *so); @@ -91,31 +91,21 @@ free(so); } -/* - * Read from so's socket into sb_snd, updating all relevant sbuf fields - * NOTE: This will only be called if it is select()ed for reading, so - * a read() of 0 (or less) means it's disconnected - */ -int -soread(so) - struct socket *so; +size_t sopreprbuf(struct socket *so, struct iovec *iov, int *np) { - int n, nn, lss, total; + int n, lss, total; struct sbuf *sb = &so->so_snd; int len = sb->sb_datalen - sb->sb_cc; - struct iovec iov[2]; int mss = so->so_tcpcb->t_maxseg; - DEBUG_CALL("soread"); + DEBUG_CALL("sopreprbuf"); DEBUG_ARG("so = %lx", (long )so); - /* - * No need to check if there's enough room to read. - * soread wouldn't have been called if there weren't - */ - len = sb->sb_datalen - sb->sb_cc; + if (len <= 0) + return 0; + iov[0].iov_base = sb->sb_wptr; iov[1].iov_base = NULL; iov[1].iov_len = 0; @@ -156,7 +146,34 @@ n = 1; } } + if (np) + *np = n; + return iov[0].iov_len + (n - 1) * iov[1].iov_len; +} + +/* + * Read from so's socket into sb_snd, updating all relevant sbuf fields + * NOTE: This will only be called if it is select()ed for reading, so + * a read() of 0 (or less) means it's disconnected + */ +int +soread(so) + struct socket *so; +{ + int n, nn; + struct sbuf *sb = &so->so_snd; + struct iovec iov[2]; + + DEBUG_CALL("soread"); + DEBUG_ARG("so = %lx", (long )so); + + /* + * No need to check if there's enough room to read. + * soread wouldn't have been called if there weren't + */ + sopreprbuf(so, iov, &n); + #ifdef HAVE_READV nn = readv(so->s, (struct iovec *)iov, n); DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn)); @@ -202,6 +219,48 @@ return nn; } +int soreadbuf(struct socket *so, const char *buf, int size) +{ + int n, nn, copy = size; + struct sbuf *sb = &so->so_snd; + struct iovec iov[2]; + + DEBUG_CALL("soreadbuf"); + DEBUG_ARG("so = %lx", (long )so); + + /* + * No need to check if there's enough room to read. + * soread wouldn't have been called if there weren't + */ + if (sopreprbuf(so, iov, &n) < size) + goto err; + + nn = MIN(iov[0].iov_len, copy); + memcpy(iov[0].iov_base, buf, nn); + + copy -= nn; + buf += nn; + + if (copy == 0) + goto done; + + memcpy(iov[1].iov_base, buf, copy); + +done: + /* Update fields */ + sb->sb_cc += size; + sb->sb_wptr += size; + if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen)) + sb->sb_wptr -= sb->sb_datalen; + return size; +err: + + sofcantrcvmore(so); + tcp_sockclosed(sototcpcb(so)); + fprintf(stderr, "soreadbuf buffer to small"); + return -1; +} + /* * Get urgent data * @@ -255,7 +314,7 @@ if (sb->sb_rptr < sb->sb_wptr) { /* We can send it directly */ - n = send(so->s, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */ + n = slirp_send(so, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */ so->so_urgc -= n; DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc)); @@ -276,7 +335,7 @@ so->so_urgc -= n; len += n; } - n = send(so->s, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */ + n = slirp_send(so, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */ #ifdef DEBUG if (n != len) DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n")); @@ -348,7 +407,7 @@ DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn)); #else - nn = send(so->s, iov[0].iov_base, iov[0].iov_len,0); + nn = slirp_send(so, iov[0].iov_base, iov[0].iov_len,0); #endif /* This should never happen, but people tell me it does *shrug* */ if (nn < 0 && (errno == EAGAIN || errno == EINTR)) @@ -365,7 +424,7 @@ #ifndef HAVE_READV if (n == 2 && nn == iov[0].iov_len) { int ret; - ret = send(so->s, iov[1].iov_base, iov[1].iov_len,0); + ret = slirp_send(so, iov[1].iov_base, iov[1].iov_len,0); if (ret > 0) nn += ret; } Modified: trunk/slirp/socket.h =================================================================== --- trunk/slirp/socket.h 2009-01-08 19:01:37 UTC (rev 6239) +++ trunk/slirp/socket.h 2009-01-08 19:18:21 UTC (rev 6240) @@ -87,5 +87,7 @@ void soisfconnected _P((register struct socket *)); void soisfdisconnected _P((struct socket *)); void sofwdrain _P((struct socket *)); +size_t sopreprbuf(struct socket *so, struct iovec *iov, int *np); +int soreadbuf(struct socket *so, const char *buf, int size); #endif /* _SOCKET_H_ */ Modified: trunk/slirp/tcp_subr.c =================================================================== --- trunk/slirp/tcp_subr.c 2009-01-08 19:01:37 UTC (rev 6239) +++ trunk/slirp/tcp_subr.c 2009-01-08 19:18:21 UTC (rev 6240) @@ -1281,6 +1281,11 @@ for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { if (ex_ptr->ex_fport == so->so_fport && command == ex_ptr->ex_addr) { + if (ex_ptr->ex_pty == 3) { + so->s = -1; + so->extra = ex_ptr->ex_exec; + return 1; + } do_pty = ex_ptr->ex_pty; goto do_exec; }