mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-02 07:13:54 -06:00
Redirect slirp traffic to/from qemu character device (Gleb Natapov)
Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6240 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
4dda406337
commit
e1c5a2b334
8 changed files with 156 additions and 25 deletions
101
slirp/socket.c
101
slirp/socket.c
|
@ -5,13 +5,13 @@
|
|||
* terms and conditions of the copyright.
|
||||
*/
|
||||
|
||||
#include "qemu-common.h"
|
||||
#define WANT_SYS_IOCTL_H
|
||||
#include <slirp.h>
|
||||
#include "ip_icmp.h"
|
||||
#ifdef __sun__
|
||||
#include <sys/filio.h>
|
||||
#endif
|
||||
#include "qemu-common.h"
|
||||
|
||||
static void sofcantrcvmore(struct socket *so);
|
||||
static void sofcantsendmore(struct socket *so);
|
||||
|
@ -91,31 +91,21 @@ sofree(so)
|
|||
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,6 +146,33 @@ soread(so)
|
|||
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);
|
||||
|
@ -202,6 +219,48 @@ soread(so)
|
|||
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 @@ sosendoob(so)
|
|||
|
||||
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 @@ sosendoob(so)
|
|||
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 @@ sowrite(so)
|
|||
|
||||
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 @@ sowrite(so)
|
|||
#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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue