Merge branch 'master' of /home/nchip/public_html/qemu into garage-push
[qemu] / slirp / socket.c
index 7bc0dc5..098132a 100644 (file)
@@ -5,7 +5,7 @@
  * terms and conditions of the copyright.
  */
 
-#define WANT_SYS_IOCTL_H
+#include "qemu-common.h"
 #include <slirp.h>
 #include "ip_icmp.h"
 #ifdef __sun__
@@ -24,12 +24,8 @@ so_init()
 #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;
 
@@ -53,7 +49,7 @@ solookup(head, laddr, lport, faddr, fport)
  * insque() it into the correct linked-list
  */
 struct socket *
-socreate()
+socreate(void)
 {
   struct socket *so;
 
@@ -70,8 +66,7 @@ socreate()
  * 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);
@@ -90,31 +85,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;
@@ -155,6 +140,32 @@ 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(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);
@@ -201,6 +212,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
  *
@@ -209,8 +262,7 @@ soread(so)
  * in the send buffer is sent as urgent data
  */
 void
-sorecvoob(so)
-       struct socket *so;
+sorecvoob(struct socket *so)
 {
        struct tcpcb *tp = sototcpcb(so);
 
@@ -237,8 +289,7 @@ sorecvoob(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 */
@@ -254,7 +305,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));
@@ -275,7 +326,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"));
@@ -296,8 +347,7 @@ sosendoob(so)
  * 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;
@@ -347,7 +397,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))
@@ -364,7 +414,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;
         }
@@ -391,8 +441,7 @@ sowrite(so)
  * 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);
@@ -419,7 +468,7 @@ sorecvfrom(so)
            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);
@@ -491,9 +540,7 @@ sorecvfrom(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;
@@ -540,11 +587,7 @@ sosendto(so, m)
  * 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;
@@ -646,8 +689,7 @@ sowwakeup(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);
@@ -655,8 +697,7 @@ soisfconnecting(so)
 }
 
 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 */
@@ -698,8 +739,7 @@ sofcantsendmore(struct socket *so)
 }
 
 void
-soisfdisconnected(so)
-       struct socket *so;
+soisfdisconnected(struct socket *so)
 {
 /*     so->so_state &= ~(SS_ISFCONNECTING|SS_ISFCONNECTED); */
 /*     close(so->s); */
@@ -714,12 +754,10 @@ soisfdisconnected(so)
  * 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);
 }
-