]> git.proxmox.com Git - qemu.git/blobdiff - slirp/tcp_input.c
hw/i386/Makefile.obj: use $(PYTHON) to run .py scripts consistently
[qemu.git] / slirp / tcp_input.c
index 980ae06d34546e150ad0975459e66cb30aa29464..f946db8dc07eaed24fa0f9ffffdd12a88c32ce76 100644 (file)
 #include <slirp.h>
 #include "ip_icmp.h"
 
-struct socket tcb;
-
 #define        TCPREXMTTHRESH 3
-struct socket *tcp_last_so = &tcb;
-
-tcp_seq tcp_iss;                /* tcp initial send seq # */
 
 #define TCP_PAWS_IDLE  (24 * 24 * 60 * 60 * PR_SLOWHZ)
 
@@ -75,8 +70,6 @@ tcp_seq tcp_iss;                /* tcp initial send seq # */
                        tp->t_flags |= TF_DELACK; \
                (tp)->rcv_nxt += (ti)->ti_len; \
                flags = (ti)->ti_flags & TH_FIN; \
-               STAT(tcpstat.tcps_rcvpack++);         \
-               STAT(tcpstat.tcps_rcvbyte += (ti)->ti_len);   \
                if (so->so_emu) { \
                       if (tcp_emu((so),(m))) sbappend((so), (m)); \
               } else \
@@ -94,8 +87,6 @@ tcp_seq tcp_iss;                /* tcp initial send seq # */
                tp->t_flags |= TF_DELACK; \
                (tp)->rcv_nxt += (ti)->ti_len; \
                flags = (ti)->ti_flags & TH_FIN; \
-               STAT(tcpstat.tcps_rcvpack++);        \
-               STAT(tcpstat.tcps_rcvbyte += (ti)->ti_len);  \
                if (so->so_emu) { \
                        if (tcp_emu((so),(m))) sbappend(so, (m)); \
                } else \
@@ -145,9 +136,7 @@ tcp_reass(register struct tcpcb *tp, register struct tcpiphdr *ti,
                i = q->ti_seq + q->ti_len - ti->ti_seq;
                if (i > 0) {
                        if (i >= ti->ti_len) {
-                               STAT(tcpstat.tcps_rcvduppack++);
-                               STAT(tcpstat.tcps_rcvdupbyte += ti->ti_len);
-                               m_freem(m);
+                               m_free(m);
                                /*
                                 * Try to present any queued data
                                 * at the left window edge to the user.
@@ -162,8 +151,6 @@ tcp_reass(register struct tcpcb *tp, register struct tcpiphdr *ti,
                }
                q = tcpiphdr_next(q);
        }
-       STAT(tcpstat.tcps_rcvoopack++);
-       STAT(tcpstat.tcps_rcvoobyte += ti->ti_len);
        ti->ti_mbuf = m;
 
        /*
@@ -183,7 +170,7 @@ tcp_reass(register struct tcpcb *tp, register struct tcpiphdr *ti,
                q = tcpiphdr_next(q);
                m = tcpiphdr_prev(q)->ti_mbuf;
                remque(tcpiphdr2qlink(tcpiphdr_prev(q)));
-               m_freem(m);
+               m_free(m);
        }
 
        /*
@@ -210,7 +197,7 @@ present:
                m = ti->ti_mbuf;
                ti = tcpiphdr_next(ti);
                if (so->so_state & SS_FCANTSENDMORE)
-                       m_freem(m);
+                       m_free(m);
                else {
                        if (so->so_emu) {
                                if (tcp_emu(so,m)) sbappend(so, m);
@@ -241,9 +228,10 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
        u_long tiwin;
        int ret;
     struct ex_list *ex_ptr;
+    Slirp *slirp;
 
        DEBUG_CALL("tcp_input");
-       DEBUG_ARGS((dfd," m = %8lx  iphlen = %2d  inso = %lx\n",
+       DEBUG_ARGS((dfd, " m = %8lx  iphlen = %2d  inso = %lx\n",
                    (long )m, iphlen, (long )inso ));
 
        /*
@@ -251,6 +239,7 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
         */
        if (m == NULL) {
                so = inso;
+               slirp = so->slirp;
 
                /* Re-set a few variables */
                tp = sototcpcb(so);
@@ -262,9 +251,8 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
 
                goto cont_conn;
        }
+       slirp = m->slirp;
 
-
-       STAT(tcpstat.tcps_rcvtotal++);
        /*
         * Get IP and TCP header together in first mbuf.
         * Note: IP leaves IP header in first mbuf.
@@ -292,10 +280,9 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
         tcpiphdr2qlink(ti)->next = tcpiphdr2qlink(ti)->prev = NULL;
         memset(&ti->ti_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr));
        ti->ti_x1 = 0;
-       ti->ti_len = htons((u_int16_t)tlen);
+       ti->ti_len = htons((uint16_t)tlen);
        len = sizeof(struct ip ) + tlen;
        if(cksum(m, len)) {
-         STAT(tcpstat.tcps_rcvbadsum++);
          goto drop;
        }
 
@@ -305,7 +292,6 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
         */
        off = ti->ti_off << 2;
        if (off < sizeof (struct tcphdr) || off > tlen) {
-         STAT(tcpstat.tcps_rcvbadoff++);
          goto drop;
        }
        tlen -= off;
@@ -330,30 +316,19 @@ 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_restrict) {
-        for (ex_ptr = 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.
         */
 findso:
-       so = tcp_last_so;
+       so = slirp->tcp_last_so;
        if (so->so_fport != ti->ti_dport ||
            so->so_lport != ti->ti_sport ||
            so->so_laddr.s_addr != ti->ti_src.s_addr ||
            so->so_faddr.s_addr != ti->ti_dst.s_addr) {
-               so = solookup(&tcb, ti->ti_src, ti->ti_sport,
+               so = solookup(&slirp->tcb, ti->ti_src, ti->ti_sport,
                               ti->ti_dst, ti->ti_dport);
                if (so)
-                       tcp_last_so = so;
-               STAT(tcpstat.tcps_socachemiss++);
+                       slirp->tcp_last_so = so;
        }
 
        /*
@@ -370,10 +345,26 @@ 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;
 
-         if ((so = socreate()) == NULL)
+         if ((so = socreate(slirp)) == NULL)
            goto dropwithreset;
          if (tcp_attach(so) < 0) {
            free(so); /* Not sofree (if it failed, it's not insqued) */
@@ -460,16 +451,13 @@ findso:
                                /*
                                 * this is a pure ack for outstanding data.
                                 */
-                               STAT(tcpstat.tcps_predack++);
                                if (tp->t_rtt &&
                                    SEQ_GT(ti->ti_ack, tp->t_rtseq))
                                        tcp_xmit_timer(tp, tp->t_rtt);
                                acked = ti->ti_ack - tp->snd_una;
-                               STAT(tcpstat.tcps_rcvackpack++);
-                               STAT(tcpstat.tcps_rcvackbyte += acked);
                                sbdrop(&so->so_snd, acked);
                                tp->snd_una = ti->ti_ack;
-                               m_freem(m);
+                               m_free(m);
 
                                /*
                                 * If all outstanding data are acked, stop
@@ -503,10 +491,7 @@ findso:
                         * with nothing on the reassembly queue and
                         * we have enough buffer space to take it.
                         */
-                       STAT(tcpstat.tcps_preddat++);
                        tp->rcv_nxt += ti->ti_len;
-                       STAT(tcpstat.tcps_rcvpack++);
-                       STAT(tcpstat.tcps_rcvbyte += ti->ti_len);
                        /*
                         * Add data to socket buffer.
                         */
@@ -574,12 +559,13 @@ findso:
           * If this is destined for the control address, then flag to
           * tcp_ctl once connected, otherwise connect
           */
-         if ((so->so_faddr.s_addr & vnetwork_mask.s_addr) ==
-             vnetwork_addr.s_addr) {
-           if (so->so_faddr.s_addr != vhost_addr.s_addr &&
-               so->so_faddr.s_addr != vnameserver_addr.s_addr) {
+         if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
+             slirp->vnetwork_addr.s_addr) {
+           if (so->so_faddr.s_addr != slirp->vhost_addr.s_addr &&
+               so->so_faddr.s_addr != slirp->vnameserver_addr.s_addr) {
                /* May be an add exec */
-               for(ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
+               for (ex_ptr = slirp->exec_list; ex_ptr;
+                    ex_ptr = ex_ptr->ex_next) {
                  if(ex_ptr->ex_fport == so->so_fport &&
                     so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) {
                    so->so_state |= SS_CTL;
@@ -600,7 +586,7 @@ findso:
 
          if((tcp_fconnect(so) == -1) && (errno != EINPROGRESS) && (errno != EWOULDBLOCK)) {
            u_char code=ICMP_UNREACH_NET;
-           DEBUG_MISC((dfd," tcp fconnect errno = %d-%s\n",
+           DEBUG_MISC((dfd, " tcp fconnect errno = %d-%s\n",
                        errno,strerror(errno)));
            if(errno == ECONNREFUSED) {
              /* ACK the SYN, send RST to refuse the connection */
@@ -617,7 +603,7 @@ findso:
              *ip=save_ip;
              icmp_error(m, ICMP_UNREACH,code, 0,strerror(errno));
            }
-           tp = tcp_close(tp);
+            tcp_close(tp);
            m_free(m);
          } else {
            /*
@@ -630,6 +616,7 @@ findso:
            so->so_ti = ti;
            tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
            tp->t_state = TCPS_SYN_RECEIVED;
+           tcp_template(tp);
          }
          return;
 
@@ -650,15 +637,14 @@ findso:
          if (iss)
            tp->iss = iss;
          else
-           tp->iss = tcp_iss;
-         tcp_iss += TCP_ISSINCR/2;
+           tp->iss = slirp->tcp_iss;
+         slirp->tcp_iss += TCP_ISSINCR/2;
          tp->irs = ti->ti_seq;
          tcp_sendseqinit(tp);
          tcp_rcvseqinit(tp);
          tp->t_flags |= TF_ACKNOW;
          tp->t_state = TCPS_SYN_RECEIVED;
          tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
-         STAT(tcpstat.tcps_accepts++);
          goto trimthenstep6;
        } /* case TCPS_LISTEN */
 
@@ -681,8 +667,9 @@ findso:
                        goto dropwithreset;
 
                if (tiflags & TH_RST) {
-                       if (tiflags & TH_ACK)
-                               tp = tcp_drop(tp,0); /* XXX Check t_softerror! */
+                        if (tiflags & TH_ACK) {
+                                tcp_drop(tp, 0); /* XXX Check t_softerror! */
+                        }
                        goto drop;
                }
 
@@ -699,7 +686,6 @@ findso:
                tcp_rcvseqinit(tp);
                tp->t_flags |= TF_ACKNOW;
                if (tiflags & TH_ACK && SEQ_GT(tp->snd_una, tp->iss)) {
-                       STAT(tcpstat.tcps_connects++);
                        soisfconnected(so);
                        tp->t_state = TCPS_ESTABLISHED;
 
@@ -726,8 +712,6 @@ trimthenstep6:
                        m_adj(m, -todrop);
                        ti->ti_len = tp->rcv_wnd;
                        tiflags &= ~TH_FIN;
-                       STAT(tcpstat.tcps_rcvpackafterwin++);
-                       STAT(tcpstat.tcps_rcvbyteafterwin += todrop);
                }
                tp->snd_wl1 = ti->ti_seq - 1;
                tp->rcv_up = ti->ti_seq;
@@ -768,11 +752,6 @@ trimthenstep6:
                         */
                        tp->t_flags |= TF_ACKNOW;
                        todrop = ti->ti_len;
-                       STAT(tcpstat.tcps_rcvduppack++);
-                       STAT(tcpstat.tcps_rcvdupbyte += todrop);
-               } else {
-                       STAT(tcpstat.tcps_rcvpartduppack++);
-                       STAT(tcpstat.tcps_rcvpartdupbyte += todrop);
                }
                m_adj(m, todrop);
                ti->ti_seq += todrop;
@@ -791,7 +770,6 @@ trimthenstep6:
        if ((so->so_state & SS_NOFDREF) &&
            tp->t_state > TCPS_CLOSE_WAIT && ti->ti_len) {
                tp = tcp_close(tp);
-               STAT(tcpstat.tcps_rcvafterclose++);
                goto dropwithreset;
        }
 
@@ -801,9 +779,7 @@ trimthenstep6:
         */
        todrop = (ti->ti_seq+ti->ti_len) - (tp->rcv_nxt+tp->rcv_wnd);
        if (todrop > 0) {
-               STAT(tcpstat.tcps_rcvpackafterwin++);
                if (todrop >= ti->ti_len) {
-                       STAT(tcpstat.tcps_rcvbyteafterwin += ti->ti_len);
                        /*
                         * If a new connection request is received
                         * while in TIME_WAIT, drop the old connection
@@ -826,11 +802,10 @@ trimthenstep6:
                         */
                        if (tp->rcv_wnd == 0 && ti->ti_seq == tp->rcv_nxt) {
                                tp->t_flags |= TF_ACKNOW;
-                               STAT(tcpstat.tcps_rcvwinprobe++);
-                       } else
+                       } else {
                                goto dropafterack;
-               } else
-                       STAT(tcpstat.tcps_rcvbyteafterwin += todrop);
+                       }
+               }
                m_adj(m, -todrop);
                ti->ti_len -= todrop;
                tiflags &= ~(TH_PUSH|TH_FIN);
@@ -854,14 +829,13 @@ trimthenstep6:
        case TCPS_FIN_WAIT_2:
        case TCPS_CLOSE_WAIT:
                tp->t_state = TCPS_CLOSED;
-               STAT(tcpstat.tcps_drops++);
-               tp = tcp_close(tp);
+                tcp_close(tp);
                goto drop;
 
        case TCPS_CLOSING:
        case TCPS_LAST_ACK:
        case TCPS_TIME_WAIT:
-               tp = tcp_close(tp);
+                tcp_close(tp);
                goto drop;
        }
 
@@ -893,7 +867,6 @@ trimthenstep6:
                if (SEQ_GT(tp->snd_una, ti->ti_ack) ||
                    SEQ_GT(ti->ti_ack, tp->snd_max))
                        goto dropwithreset;
-               STAT(tcpstat.tcps_connects++);
                tp->t_state = TCPS_ESTABLISHED;
                /*
                 * The sent SYN is ack'ed with our sequence number +1
@@ -944,8 +917,7 @@ trimthenstep6:
 
                if (SEQ_LEQ(ti->ti_ack, tp->snd_una)) {
                        if (ti->ti_len == 0 && tiwin == tp->snd_wnd) {
-                         STAT(tcpstat.tcps_rcvdupack++);
-                         DEBUG_MISC((dfd," dup ack  m = %lx  so = %lx \n",
+                         DEBUG_MISC((dfd, " dup ack  m = %lx  so = %lx\n",
                                      (long )m, (long )so));
                                /*
                                 * If we have outstanding data (other than
@@ -1012,12 +984,9 @@ trimthenstep6:
                        tp->snd_cwnd = tp->snd_ssthresh;
                tp->t_dupacks = 0;
                if (SEQ_GT(ti->ti_ack, tp->snd_max)) {
-                       STAT(tcpstat.tcps_rcvacktoomuch++);
                        goto dropafterack;
                }
                acked = ti->ti_ack - tp->snd_una;
-               STAT(tcpstat.tcps_rcvackpack++);
-               STAT(tcpstat.tcps_rcvackbyte += acked);
 
                /*
                 * If transmit timer is running and timed sequence
@@ -1113,7 +1082,7 @@ trimthenstep6:
                 */
                case TCPS_LAST_ACK:
                        if (ourfinisacked) {
-                               tp = tcp_close(tp);
+                                tcp_close(tp);
                                goto drop;
                        }
                        break;
@@ -1138,10 +1107,6 @@ step6:
            (SEQ_LT(tp->snd_wl1, ti->ti_seq) ||
            (tp->snd_wl1 == ti->ti_seq && (SEQ_LT(tp->snd_wl2, ti->ti_ack) ||
            (tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd))))) {
-               /* keep track of pure window updates */
-               if (ti->ti_len == 0 &&
-                   tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd)
-                       STAT(tcpstat.tcps_rcvwinupd++);
                tp->snd_wnd = tiwin;
                tp->snd_wl1 = ti->ti_seq;
                tp->snd_wl2 = ti->ti_ack;
@@ -1197,6 +1162,16 @@ step6:
                        tp->rcv_up = tp->rcv_nxt;
 dodata:
 
+       /*
+        * If this is a small packet, then ACK now - with Nagel
+        *      congestion avoidance sender won't send more until
+        *      he gets an ACK.
+        */
+       if (ti->ti_len && (unsigned)ti->ti_len <= 5 &&
+           ((struct tcpiphdr_2 *)ti)->first_char == (char)27) {
+               tp->t_flags |= TF_ACKNOW;
+       }
+
        /*
         * Process the segment text, merging it into the TCP sequencing queue,
         * and arranging for acknowledgment of receipt if necessary.
@@ -1208,12 +1183,6 @@ dodata:
        if ((ti->ti_len || (tiflags&TH_FIN)) &&
            TCPS_HAVERCVDFIN(tp->t_state) == 0) {
                TCP_REASS(tp, ti, m, so, tiflags);
-               /*
-                * Note the amount of data that peer has sent into
-                * our window, in order to estimate the sender's
-                * buffer size.
-                */
-               len = so->so_rcv.sb_datalen - (tp->rcv_adv - tp->rcv_nxt);
        } else {
                m_free(m);
                tiflags &= ~TH_FIN;
@@ -1281,18 +1250,6 @@ dodata:
                }
        }
 
-       /*
-        * If this is a small packet, then ACK now - with Nagel
-        *      congestion avoidance sender won't send more until
-        *      he gets an ACK.
-        *
-        * See above.
-        */
-       if (ti->ti_len && (unsigned)ti->ti_len <= 5 &&
-           ((struct tcpiphdr_2 *)ti)->first_char == (char)27) {
-               tp->t_flags |= TF_ACKNOW;
-       }
-
        /*
         * Return any desired output.
         */
@@ -1308,7 +1265,7 @@ dropafterack:
         */
        if (tiflags & TH_RST)
                goto drop;
-       m_freem(m);
+       m_free(m);
        tp->t_flags |= TF_ACKNOW;
        (void) tcp_output(tp);
        return;
@@ -1330,18 +1287,16 @@ drop:
         * Drop space held by incoming segment and return.
         */
        m_free(m);
-
-       return;
 }
 
 static void
 tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt, struct tcpiphdr *ti)
 {
-       u_int16_t mss;
+       uint16_t mss;
        int opt, optlen;
 
        DEBUG_CALL("tcp_dooptions");
-       DEBUG_ARGS((dfd," tp = %lx  cnt=%i \n", (long )tp, cnt));
+       DEBUG_ARGS((dfd, " tp = %lx  cnt=%i\n", (long)tp, cnt));
 
        for (; cnt > 0; cnt -= optlen, cp += optlen) {
                opt = cp[0];
@@ -1425,7 +1380,6 @@ tcp_xmit_timer(register struct tcpcb *tp, int rtt)
        DEBUG_ARG("tp = %lx", (long)tp);
        DEBUG_ARG("rtt = %d", rtt);
 
-       STAT(tcpstat.tcps_rttupdated++);
        if (tp->t_srtt != 0) {
                /*
                 * srtt is stored as fixed point with 3 bits after the