* terms and conditions of the copyright.
*/
-#define WANT_SYS_IOCTL_H
+#include "qemu-common.h"
#include <slirp.h>
#include "ip_icmp.h"
#ifdef __sun__
#endif
struct socket *
-solookup(head, laddr, lport, faddr, fport)
- struct socket *head;
- struct in_addr laddr;
- u_int lport;
- struct in_addr faddr;
- u_int fport;
+solookup(struct socket *head, struct in_addr laddr, u_int lport,
+ struct in_addr faddr, u_int fport)
{
struct socket *so;
* insque() it into the correct linked-list
*/
struct socket *
-socreate()
+socreate(void)
{
struct socket *so;
* remque and free a socket, clobber cache
*/
void
-sofree(so)
- struct socket *so;
+sofree(struct socket *so)
{
if (so->so_emu==EMU_RSH && so->extra) {
sofree(so->extra);
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;
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(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);
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
*
* in the send buffer is sent as urgent data
*/
void
-sorecvoob(so)
- struct socket *so;
+sorecvoob(struct socket *so)
{
struct tcpcb *tp = sototcpcb(so);
* There's a lot duplicated code here, but...
*/
int
-sosendoob(so)
- struct socket *so;
+sosendoob(struct socket *so)
{
struct sbuf *sb = &so->so_rcv;
char buff[2048]; /* XXX Shouldn't be sending more oob data than this */
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));
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"));
* updating all sbuf field as necessary
*/
int
-sowrite(so)
- struct socket *so;
+sowrite(struct socket *so)
{
int n,nn;
struct sbuf *sb = &so->so_rcv;
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))
#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;
}
* recvfrom() a UDP socket
*/
void
-sorecvfrom(so)
- struct socket *so;
+sorecvfrom(struct socket *so)
{
struct sockaddr_in addr;
socklen_t addrlen = sizeof(struct sockaddr_in);
icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
} else {
icmp_reflect(so->so_m);
- so->so_m = 0; /* Don't m_free() it again! */
+ so->so_m = NULL; /* Don't m_free() it again! */
}
/* No need for this socket anymore, udp_detach it */
udp_detach(so);
* sendto() a socket
*/
int
-sosendto(so, m)
- struct socket *so;
- struct mbuf *m;
+sosendto(struct socket *so, struct mbuf *m)
{
int ret;
struct sockaddr_in addr;
* XXX This should really be tcp_listen
*/
struct socket *
-solisten(port, laddr, lport, flags)
- u_int port;
- u_int32_t laddr;
- u_int lport;
- int flags;
+solisten(u_int port, u_int32_t laddr, u_int lport, int flags)
{
struct sockaddr_in addr;
struct socket *so;
* times each when only 1 was needed
*/
void
-soisfconnecting(so)
- register struct socket *so;
+soisfconnecting(struct socket *so)
{
so->so_state &= ~(SS_NOFDREF|SS_ISFCONNECTED|SS_FCANTRCVMORE|
SS_FCANTSENDMORE|SS_FWDRAIN);
}
void
-soisfconnected(so)
- register struct socket *so;
+soisfconnected(struct socket *so)
{
so->so_state &= ~(SS_ISFCONNECTING|SS_FWDRAIN|SS_NOFDREF);
so->so_state |= SS_ISFCONNECTED; /* Clobber other states */
}
void
-soisfdisconnected(so)
- struct socket *so;
+soisfdisconnected(struct socket *so)
{
/* so->so_state &= ~(SS_ISFCONNECTING|SS_ISFCONNECTED); */
/* close(so->s); */
* Set CANTSENDMORE once all data has been write()n
*/
void
-sofwdrain(so)
- struct socket *so;
+sofwdrain(struct socket *so)
{
if (so->so_rcv.sb_cc)
so->so_state |= SS_FWDRAIN;
else
sofcantsendmore(so);
}
-