Diff for /qemu/slirp/tcp_input.c between versions 1.1.1.4 and 1.1.1.5

version 1.1.1.4, 2018/04/24 16:54:51 version 1.1.1.5, 2018/04/24 17:25:56
Line 41 Line 41
 #include <slirp.h>  #include <slirp.h>
 #include "ip_icmp.h"  #include "ip_icmp.h"
   
 struct socket tcb;  
   
 #define TCPREXMTTHRESH 3  #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)  #define TCP_PAWS_IDLE   (24 * 24 * 60 * 60 * PR_SLOWHZ)
   
Line 75  tcp_seq tcp_iss;                /* tcp i Line 70  tcp_seq tcp_iss;                /* tcp i
                        tp->t_flags |= TF_DELACK; \                         tp->t_flags |= TF_DELACK; \
                (tp)->rcv_nxt += (ti)->ti_len; \                 (tp)->rcv_nxt += (ti)->ti_len; \
                flags = (ti)->ti_flags & TH_FIN; \                 flags = (ti)->ti_flags & TH_FIN; \
                STAT(tcpstat.tcps_rcvpack++);         \  
                STAT(tcpstat.tcps_rcvbyte += (ti)->ti_len);   \  
                if (so->so_emu) { \                 if (so->so_emu) { \
                        if (tcp_emu((so),(m))) sbappend((so), (m)); \                         if (tcp_emu((so),(m))) sbappend((so), (m)); \
                } else \                 } else \
                        sbappend((so), (m)); \                         sbappend((so), (m)); \
 /*               sorwakeup(so); */ \  
         } else {\          } else {\
                (flags) = tcp_reass((tp), (ti), (m)); \                 (flags) = tcp_reass((tp), (ti), (m)); \
                tp->t_flags |= TF_ACKNOW; \                 tp->t_flags |= TF_ACKNOW; \
Line 95  tcp_seq tcp_iss;                /* tcp i Line 87  tcp_seq tcp_iss;                /* tcp i
                 tp->t_flags |= TF_DELACK; \                  tp->t_flags |= TF_DELACK; \
                 (tp)->rcv_nxt += (ti)->ti_len; \                  (tp)->rcv_nxt += (ti)->ti_len; \
                 flags = (ti)->ti_flags & TH_FIN; \                  flags = (ti)->ti_flags & TH_FIN; \
                 STAT(tcpstat.tcps_rcvpack++);        \  
                 STAT(tcpstat.tcps_rcvbyte += (ti)->ti_len);  \  
                 if (so->so_emu) { \                  if (so->so_emu) { \
                         if (tcp_emu((so),(m))) sbappend(so, (m)); \                          if (tcp_emu((so),(m))) sbappend(so, (m)); \
                 } else \                  } else \
                         sbappend((so), (m)); \                          sbappend((so), (m)); \
 /*              sorwakeup(so); */ \  
         } else { \          } else { \
                 (flags) = tcp_reass((tp), (ti), (m)); \                  (flags) = tcp_reass((tp), (ti), (m)); \
                 tp->t_flags |= TF_ACKNOW; \                  tp->t_flags |= TF_ACKNOW; \
Line 121  tcp_reass(register struct tcpcb *tp, reg Line 110  tcp_reass(register struct tcpcb *tp, reg
         int flags;          int flags;
   
         /*          /*
          * Call with ti==0 after become established to           * Call with ti==NULL after become established to
          * force pre-ESTABLISHED data up to user socket.           * force pre-ESTABLISHED data up to user socket.
          */           */
         if (ti == 0)          if (ti == NULL)
                 goto present;                  goto present;
   
         /*          /*
Line 147  tcp_reass(register struct tcpcb *tp, reg Line 136  tcp_reass(register struct tcpcb *tp, reg
                 i = q->ti_seq + q->ti_len - ti->ti_seq;                  i = q->ti_seq + q->ti_len - ti->ti_seq;
                 if (i > 0) {                  if (i > 0) {
                         if (i >= ti->ti_len) {                          if (i >= ti->ti_len) {
                                 STAT(tcpstat.tcps_rcvduppack++);  
                                 STAT(tcpstat.tcps_rcvdupbyte += ti->ti_len);  
                                 m_freem(m);                                  m_freem(m);
                                 /*                                  /*
                                  * Try to present any queued data                                   * Try to present any queued data
Line 164  tcp_reass(register struct tcpcb *tp, reg Line 151  tcp_reass(register struct tcpcb *tp, reg
                 }                  }
                 q = tcpiphdr_next(q);                  q = tcpiphdr_next(q);
         }          }
         STAT(tcpstat.tcps_rcvoopack++);  
         STAT(tcpstat.tcps_rcvoobyte += ti->ti_len);  
         ti->ti_mbuf = m;          ti->ti_mbuf = m;
   
         /*          /*
Line 211  present: Line 196  present:
                 remque(tcpiphdr2qlink(ti));                  remque(tcpiphdr2qlink(ti));
                 m = ti->ti_mbuf;                  m = ti->ti_mbuf;
                 ti = tcpiphdr_next(ti);                  ti = tcpiphdr_next(ti);
 /*              if (so->so_state & SS_FCANTRCVMORE) */  
                 if (so->so_state & SS_FCANTSENDMORE)                  if (so->so_state & SS_FCANTSENDMORE)
                         m_freem(m);                          m_freem(m);
                 else {                  else {
Line 221  present: Line 205  present:
                                 sbappend(so, m);                                  sbappend(so, m);
                 }                  }
         } while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt);          } while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt);
 /*      sorwakeup(so); */  
         return (flags);          return (flags);
 }  }
   
Line 230  present: Line 213  present:
  * protocol specification dated September, 1981 very closely.   * protocol specification dated September, 1981 very closely.
  */   */
 void  void
 tcp_input(m, iphlen, inso)  tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
         register struct mbuf *m;  
         int iphlen;  
         struct socket *inso;  
 {  {
         struct ip save_ip, *ip;          struct ip save_ip, *ip;
         register struct tcpiphdr *ti;          register struct tcpiphdr *ti;
         caddr_t optp = NULL;          caddr_t optp = NULL;
         int optlen = 0;          int optlen = 0;
         int len, tlen, off;          int len, tlen, off;
         register struct tcpcb *tp = 0;          register struct tcpcb *tp = NULL;
         register int tiflags;          register int tiflags;
         struct socket *so = 0;          struct socket *so = NULL;
         int todrop, acked, ourfinisacked, needoutput = 0;          int todrop, acked, ourfinisacked, needoutput = 0;
 /*      int dropsocket = 0; */  
         int iss = 0;          int iss = 0;
         u_long tiwin;          u_long tiwin;
         int ret;          int ret;
 /*      int ts_present = 0; */  
     struct ex_list *ex_ptr;      struct ex_list *ex_ptr;
       Slirp *slirp;
   
         DEBUG_CALL("tcp_input");          DEBUG_CALL("tcp_input");
         DEBUG_ARGS((dfd," m = %8lx  iphlen = %2d  inso = %lx\n",          DEBUG_ARGS((dfd," m = %8lx  iphlen = %2d  inso = %lx\n",
Line 260  tcp_input(m, iphlen, inso) Line 239  tcp_input(m, iphlen, inso)
          */           */
         if (m == NULL) {          if (m == NULL) {
                 so = inso;                  so = inso;
                   slirp = so->slirp;
   
                 /* Re-set a few variables */                  /* Re-set a few variables */
                 tp = sototcpcb(so);                  tp = sototcpcb(so);
                 m = so->so_m;                  m = so->so_m;
                 so->so_m = 0;                  so->so_m = NULL;
                 ti = so->so_ti;                  ti = so->so_ti;
                 tiwin = ti->ti_win;                  tiwin = ti->ti_win;
                 tiflags = ti->ti_flags;                  tiflags = ti->ti_flags;
   
                 goto cont_conn;                  goto cont_conn;
         }          }
           slirp = m->slirp;
   
   
         STAT(tcpstat.tcps_rcvtotal++);  
         /*          /*
          * Get IP and TCP header together in first mbuf.           * Get IP and TCP header together in first mbuf.
          * Note: IP leaves IP header in first mbuf.           * Note: IP leaves IP header in first mbuf.
Line 298  tcp_input(m, iphlen, inso) Line 277  tcp_input(m, iphlen, inso)
          * Checksum extended TCP header and data.           * Checksum extended TCP header and data.
          */           */
         tlen = ((struct ip *)ti)->ip_len;          tlen = ((struct ip *)ti)->ip_len;
         tcpiphdr2qlink(ti)->next = tcpiphdr2qlink(ti)->prev = 0;          tcpiphdr2qlink(ti)->next = tcpiphdr2qlink(ti)->prev = NULL;
     memset(&ti->ti_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr));          memset(&ti->ti_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr));
         ti->ti_x1 = 0;          ti->ti_x1 = 0;
         ti->ti_len = htons((u_int16_t)tlen);          ti->ti_len = htons((u_int16_t)tlen);
         len = sizeof(struct ip ) + tlen;          len = sizeof(struct ip ) + tlen;
         /* keep checksum for ICMP reply  
          * ti->ti_sum = cksum(m, len);  
          * if (ti->ti_sum) { */  
         if(cksum(m, len)) {          if(cksum(m, len)) {
           STAT(tcpstat.tcps_rcvbadsum++);  
           goto drop;            goto drop;
         }          }
   
Line 317  tcp_input(m, iphlen, inso) Line 292  tcp_input(m, iphlen, inso)
          */           */
         off = ti->ti_off << 2;          off = ti->ti_off << 2;
         if (off < sizeof (struct tcphdr) || off > tlen) {          if (off < sizeof (struct tcphdr) || off > tlen) {
           STAT(tcpstat.tcps_rcvbadoff++);  
           goto drop;            goto drop;
         }          }
         tlen -= off;          tlen -= off;
Line 325  tcp_input(m, iphlen, inso) Line 299  tcp_input(m, iphlen, inso)
         if (off > sizeof (struct tcphdr)) {          if (off > sizeof (struct tcphdr)) {
           optlen = off - sizeof (struct tcphdr);            optlen = off - sizeof (struct tcphdr);
           optp = mtod(m, caddr_t) + sizeof (struct tcpiphdr);            optp = mtod(m, caddr_t) + sizeof (struct tcpiphdr);
   
                 /*  
                  * Do quick retrieval of timestamp options ("options  
                  * prediction?").  If timestamp is the only option and it's  
                  * formatted as recommended in RFC 1323 appendix A, we  
                  * quickly get the values now and not bother calling  
                  * tcp_dooptions(), etc.  
                  */  
 /*              if ((optlen == TCPOLEN_TSTAMP_APPA ||  
  *                   (optlen > TCPOLEN_TSTAMP_APPA &&  
  *                      optp[TCPOLEN_TSTAMP_APPA] == TCPOPT_EOL)) &&  
  *                   *(u_int32_t *)optp == htonl(TCPOPT_TSTAMP_HDR) &&  
  *                   (ti->ti_flags & TH_SYN) == 0) {  
  *                      ts_present = 1;  
  *                      ts_val = ntohl(*(u_int32_t *)(optp + 4));  
  *                      ts_ecr = ntohl(*(u_int32_t *)(optp + 8));  
  *                      optp = NULL;   / * we've parsed the options * /  
  *              }  
  */  
         }          }
         tiflags = ti->ti_flags;          tiflags = ti->ti_flags;
   
Line 361  tcp_input(m, iphlen, inso) Line 316  tcp_input(m, iphlen, inso)
         m->m_data += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);          m->m_data += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
         m->m_len  -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);          m->m_len  -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
   
     if (slirp_restrict) {      if (slirp->restricted) {
         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 == ti->ti_dport &&              if (ex_ptr->ex_fport == ti->ti_dport &&
                     (ntohl(ti->ti_dst.s_addr) & 0xff) == ex_ptr->ex_addr)                  ti->ti_dst.s_addr == ex_ptr->ex_addr.s_addr) {
                 break;                  break;
               }
           }
         if (!ex_ptr)          if (!ex_ptr)
             goto drop;              goto drop;
     }      }
Line 374  tcp_input(m, iphlen, inso) Line 330  tcp_input(m, iphlen, inso)
          * Locate pcb for segment.           * Locate pcb for segment.
          */           */
 findso:  findso:
         so = tcp_last_so;          so = slirp->tcp_last_so;
         if (so->so_fport != ti->ti_dport ||          if (so->so_fport != ti->ti_dport ||
             so->so_lport != ti->ti_sport ||              so->so_lport != ti->ti_sport ||
             so->so_laddr.s_addr != ti->ti_src.s_addr ||              so->so_laddr.s_addr != ti->ti_src.s_addr ||
             so->so_faddr.s_addr != ti->ti_dst.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);                                 ti->ti_dst, ti->ti_dport);
                 if (so)                  if (so)
                         tcp_last_so = so;                          slirp->tcp_last_so = so;
                 STAT(tcpstat.tcps_socachemiss++);  
         }          }
   
         /*          /*
Line 399  findso: Line 354  findso:
          * the only flag set, then create a session, mark it           * the only flag set, then create a session, mark it
          * as if it was LISTENING, and continue...           * as if it was LISTENING, and continue...
          */           */
         if (so == 0) {          if (so == NULL) {
           if ((tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) != TH_SYN)            if ((tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) != TH_SYN)
             goto dropwithreset;              goto dropwithreset;
   
           if ((so = socreate()) == NULL)            if ((so = socreate(slirp)) == NULL)
             goto dropwithreset;              goto dropwithreset;
           if (tcp_attach(so) < 0) {            if (tcp_attach(so) < 0) {
             free(so); /* Not sofree (if it failed, it's not insqued) */              free(so); /* Not sofree (if it failed, it's not insqued) */
Line 413  findso: Line 368  findso:
           sbreserve(&so->so_snd, TCP_SNDSPACE);            sbreserve(&so->so_snd, TCP_SNDSPACE);
           sbreserve(&so->so_rcv, TCP_RCVSPACE);            sbreserve(&so->so_rcv, TCP_RCVSPACE);
   
           /*            tcp_last_so = so; */  /* XXX ? */  
           /*            tp = sototcpcb(so);    */  
   
           so->so_laddr = ti->ti_src;            so->so_laddr = ti->ti_src;
           so->so_lport = ti->ti_sport;            so->so_lport = ti->ti_sport;
           so->so_faddr = ti->ti_dst;            so->so_faddr = ti->ti_dst;
Line 439  findso: Line 391  findso:
         tp = sototcpcb(so);          tp = sototcpcb(so);
   
         /* XXX Should never fail */          /* XXX Should never fail */
         if (tp == 0)          if (tp == NULL)
                 goto dropwithreset;                  goto dropwithreset;
         if (tp->t_state == TCPS_CLOSED)          if (tp->t_state == TCPS_CLOSED)
                 goto drop;                  goto drop;
   
         /* Unscale the window into a 32-bit value. */          tiwin = ti->ti_win;
 /*      if ((tiflags & TH_SYN) == 0)  
  *              tiwin = ti->ti_win << tp->snd_scale;  
  *      else  
  */  
                 tiwin = ti->ti_win;  
   
         /*          /*
          * Segment received on connection.           * Segment received on connection.
Line 467  findso: Line 414  findso:
          */           */
         if (optp && tp->t_state != TCPS_LISTEN)          if (optp && tp->t_state != TCPS_LISTEN)
                 tcp_dooptions(tp, (u_char *)optp, optlen, ti);                  tcp_dooptions(tp, (u_char *)optp, optlen, ti);
 /* , */  
 /*                      &ts_present, &ts_val, &ts_ecr); */  
   
         /*          /*
          * Header prediction: check for the two common cases           * Header prediction: check for the two common cases
Line 490  findso: Line 435  findso:
          */           */
         if (tp->t_state == TCPS_ESTABLISHED &&          if (tp->t_state == TCPS_ESTABLISHED &&
             (tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) == TH_ACK &&              (tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) == TH_ACK &&
 /*          (!ts_present || TSTMP_GEQ(ts_val, tp->ts_recent)) && */  
             ti->ti_seq == tp->rcv_nxt &&              ti->ti_seq == tp->rcv_nxt &&
             tiwin && tiwin == tp->snd_wnd &&              tiwin && tiwin == tp->snd_wnd &&
             tp->snd_nxt == tp->snd_max) {              tp->snd_nxt == tp->snd_max) {
                 /*  
                  * If last ACK falls within this segment's sequence numbers,  
                  *  record the timestamp.  
                  */  
 /*              if (ts_present && SEQ_LEQ(ti->ti_seq, tp->last_ack_sent) &&  
  *                 SEQ_LT(tp->last_ack_sent, ti->ti_seq + ti->ti_len)) {  
  *                      tp->ts_recent_age = tcp_now;  
  *                      tp->ts_recent = ts_val;  
  *              }  
  */  
                 if (ti->ti_len == 0) {                  if (ti->ti_len == 0) {
                         if (SEQ_GT(ti->ti_ack, tp->snd_una) &&                          if (SEQ_GT(ti->ti_ack, tp->snd_una) &&
                             SEQ_LEQ(ti->ti_ack, tp->snd_max) &&                              SEQ_LEQ(ti->ti_ack, tp->snd_max) &&
Line 511  findso: Line 445  findso:
                                 /*                                  /*
                                  * this is a pure ack for outstanding data.                                   * this is a pure ack for outstanding data.
                                  */                                   */
                                 STAT(tcpstat.tcps_predack++);                                  if (tp->t_rtt &&
 /*                              if (ts_present)                                      SEQ_GT(ti->ti_ack, tp->t_rtseq))
  *                                      tcp_xmit_timer(tp, tcp_now-ts_ecr+1);  
  *                              else  
  */                                  if (tp->t_rtt &&  
                                             SEQ_GT(ti->ti_ack, tp->t_rtseq))  
                                         tcp_xmit_timer(tp, tp->t_rtt);                                          tcp_xmit_timer(tp, tp->t_rtt);
                                 acked = ti->ti_ack - tp->snd_una;                                  acked = ti->ti_ack - tp->snd_una;
                                 STAT(tcpstat.tcps_rcvackpack++);  
                                 STAT(tcpstat.tcps_rcvackbyte += acked);  
                                 sbdrop(&so->so_snd, acked);                                  sbdrop(&so->so_snd, acked);
                                 tp->snd_una = ti->ti_ack;                                  tp->snd_una = ti->ti_ack;
                                 m_freem(m);                                  m_freem(m);
Line 540  findso: Line 468  findso:
                                         tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;                                          tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
   
                                 /*                                  /*
                                  * There's room in so_snd, sowwakup will read()  
                                  * from the socket if we can  
                                  */  
 /*                              if (so->so_snd.sb_flags & SB_NOTIFY)  
  *                                      sowwakeup(so);  
  */  
                                 /*  
                                  * This is called because sowwakeup might have                                   * This is called because sowwakeup might have
                                  * put data into so_snd.  Since we don't so sowwakeup,                                   * put data into so_snd.  Since we don't so sowwakeup,
                                  * we don't need this.. XXX???                                   * we don't need this.. XXX???
Line 564  findso: Line 485  findso:
                          * with nothing on the reassembly queue and                           * with nothing on the reassembly queue and
                          * we have enough buffer space to take it.                           * we have enough buffer space to take it.
                          */                           */
                         STAT(tcpstat.tcps_preddat++);  
                         tp->rcv_nxt += ti->ti_len;                          tp->rcv_nxt += ti->ti_len;
                         STAT(tcpstat.tcps_rcvpack++);  
                         STAT(tcpstat.tcps_rcvbyte += ti->ti_len);  
                         /*                          /*
                          * Add data to socket buffer.                           * Add data to socket buffer.
                          */                           */
Line 577  findso: Line 495  findso:
                                 sbappend(so, m);                                  sbappend(so, m);
   
                         /*                          /*
                          * XXX This is called when data arrives.  Later, check  
                          * if we can actually write() to the socket  
                          * XXX Need to check? It's be NON_BLOCKING  
                          */  
 /*                      sorwakeup(so); */  
   
                         /*  
                          * If this is a short packet, then ACK now - with Nagel                           * If this is a short packet, then ACK now - with Nagel
                          *      congestion avoidance sender won't send more until                           *      congestion avoidance sender won't send more until
                          *      he gets an ACK.                           *      he gets an ACK.
Line 642  findso: Line 553  findso:
            * If this is destined for the control address, then flag to             * If this is destined for the control address, then flag to
            * tcp_ctl once connected, otherwise connect             * tcp_ctl once connected, otherwise connect
            */             */
           if ((so->so_faddr.s_addr&htonl(0xffffff00)) == special_addr.s_addr) {            if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
             int lastbyte=ntohl(so->so_faddr.s_addr) & 0xff;                slirp->vnetwork_addr.s_addr) {
             if (lastbyte!=CTL_ALIAS && lastbyte!=CTL_DNS) {              if (so->so_faddr.s_addr != slirp->vhost_addr.s_addr &&
 #if 0                  so->so_faddr.s_addr != slirp->vnameserver_addr.s_addr) {
               if(lastbyte==CTL_CMD || lastbyte==CTL_EXEC) {  
                 /* Command or exec adress */  
                 so->so_state |= SS_CTL;  
               } else  
 #endif  
               {  
                 /* May be an add exec */                  /* 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 &&                    if(ex_ptr->ex_fport == so->so_fport &&
                      lastbyte == ex_ptr->ex_addr) {                       so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) {
                     so->so_state |= SS_CTL;                      so->so_state |= SS_CTL;
                     break;                      break;
                   }                    }
                 }                  }
               }                  if (so->so_state & SS_CTL) {
               if(so->so_state & SS_CTL) goto cont_input;                      goto cont_input;
                   }
             }              }
             /* CTL_ALIAS: Do nothing, tcp_fconnect will be called on it */              /* CTL_ALIAS: Do nothing, tcp_fconnect will be called on it */
           }            }
Line 719  findso: Line 626  findso:
   
           if (optp)            if (optp)
             tcp_dooptions(tp, (u_char *)optp, optlen, ti);              tcp_dooptions(tp, (u_char *)optp, optlen, ti);
           /* , */  
           /*                            &ts_present, &ts_val, &ts_ecr); */  
   
           if (iss)            if (iss)
             tp->iss = iss;              tp->iss = iss;
           else            else
             tp->iss = tcp_iss;              tp->iss = slirp->tcp_iss;
           tcp_iss += TCP_ISSINCR/2;            slirp->tcp_iss += TCP_ISSINCR/2;
           tp->irs = ti->ti_seq;            tp->irs = ti->ti_seq;
           tcp_sendseqinit(tp);            tcp_sendseqinit(tp);
           tcp_rcvseqinit(tp);            tcp_rcvseqinit(tp);
           tp->t_flags |= TF_ACKNOW;            tp->t_flags |= TF_ACKNOW;
           tp->t_state = TCPS_SYN_RECEIVED;            tp->t_state = TCPS_SYN_RECEIVED;
           tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;            tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
           STAT(tcpstat.tcps_accepts++);  
           goto trimthenstep6;            goto trimthenstep6;
         } /* case TCPS_LISTEN */          } /* case TCPS_LISTEN */
   
Line 774  findso: Line 678  findso:
                 tcp_rcvseqinit(tp);                  tcp_rcvseqinit(tp);
                 tp->t_flags |= TF_ACKNOW;                  tp->t_flags |= TF_ACKNOW;
                 if (tiflags & TH_ACK && SEQ_GT(tp->snd_una, tp->iss)) {                  if (tiflags & TH_ACK && SEQ_GT(tp->snd_una, tp->iss)) {
                         STAT(tcpstat.tcps_connects++);  
                         soisfconnected(so);                          soisfconnected(so);
                         tp->t_state = TCPS_ESTABLISHED;                          tp->t_state = TCPS_ESTABLISHED;
   
                         /* Do window scaling on this connection? */  
 /*                      if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==  
  *                              (TF_RCVD_SCALE|TF_REQ_SCALE)) {  
  *                              tp->snd_scale = tp->requested_s_scale;  
  *                              tp->rcv_scale = tp->request_r_scale;  
  *                      }  
  */  
                         (void) tcp_reass(tp, (struct tcpiphdr *)0,                          (void) tcp_reass(tp, (struct tcpiphdr *)0,
                                 (struct mbuf *)0);                                  (struct mbuf *)0);
                         /*                          /*
Line 808  trimthenstep6: Line 704  trimthenstep6:
                         m_adj(m, -todrop);                          m_adj(m, -todrop);
                         ti->ti_len = tp->rcv_wnd;                          ti->ti_len = tp->rcv_wnd;
                         tiflags &= ~TH_FIN;                          tiflags &= ~TH_FIN;
                         STAT(tcpstat.tcps_rcvpackafterwin++);  
                         STAT(tcpstat.tcps_rcvbyteafterwin += todrop);  
                 }                  }
                 tp->snd_wl1 = ti->ti_seq - 1;                  tp->snd_wl1 = ti->ti_seq - 1;
                 tp->rcv_up = ti->ti_seq;                  tp->rcv_up = ti->ti_seq;
Line 817  trimthenstep6: Line 711  trimthenstep6:
         } /* switch tp->t_state */          } /* switch tp->t_state */
         /*          /*
          * States other than LISTEN or SYN_SENT.           * States other than LISTEN or SYN_SENT.
          * First check timestamp, if present.           * Check that at least some bytes of segment are within
          * Then check that at least some bytes of segment are within  
          * receive window.  If segment begins before rcv_nxt,           * receive window.  If segment begins before rcv_nxt,
          * drop leading data (and SYN); if nothing left, just ack.           * drop leading data (and SYN); if nothing left, just ack.
          *  
          * RFC 1323 PAWS: If we have a timestamp reply on this segment  
          * and it's less than ts_recent, drop it.  
          */           */
 /*      if (ts_present && (tiflags & TH_RST) == 0 && tp->ts_recent &&  
  *          TSTMP_LT(ts_val, tp->ts_recent)) {  
  *  
  */             /* Check to see if ts_recent is over 24 days old.  */  
 /*              if ((int)(tcp_now - tp->ts_recent_age) > TCP_PAWS_IDLE) {  
  */                     /*  
  *                       * Invalidate ts_recent.  If this segment updates  
  *                       * ts_recent, the age will be reset later and ts_recent  
  *                       * will get a valid value.  If it does not, setting  
  *                       * ts_recent to zero will at least satisfy the  
  *                       * requirement that zero be placed in the timestamp  
  *                       * echo reply when ts_recent isn't valid.  The  
  *                       * age isn't reset until we get a valid ts_recent  
  *                       * because we don't want out-of-order segments to be  
  *                       * dropped when ts_recent is old.  
  *                       */  
 /*                      tp->ts_recent = 0;  
  *              } else {  
  *                      tcpstat.tcps_rcvduppack++;  
  *                      tcpstat.tcps_rcvdupbyte += ti->ti_len;  
  *                      tcpstat.tcps_pawsdrop++;  
  *                      goto dropafterack;  
  *              }  
  *      }  
  */  
   
         todrop = tp->rcv_nxt - ti->ti_seq;          todrop = tp->rcv_nxt - ti->ti_seq;
         if (todrop > 0) {          if (todrop > 0) {
                 if (tiflags & TH_SYN) {                  if (tiflags & TH_SYN) {
Line 880  trimthenstep6: Line 744  trimthenstep6:
                          */                           */
                         tp->t_flags |= TF_ACKNOW;                          tp->t_flags |= TF_ACKNOW;
                         todrop = ti->ti_len;                          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);                  m_adj(m, todrop);
                 ti->ti_seq += todrop;                  ti->ti_seq += todrop;
Line 903  trimthenstep6: Line 762  trimthenstep6:
         if ((so->so_state & SS_NOFDREF) &&          if ((so->so_state & SS_NOFDREF) &&
             tp->t_state > TCPS_CLOSE_WAIT && ti->ti_len) {              tp->t_state > TCPS_CLOSE_WAIT && ti->ti_len) {
                 tp = tcp_close(tp);                  tp = tcp_close(tp);
                 STAT(tcpstat.tcps_rcvafterclose++);  
                 goto dropwithreset;                  goto dropwithreset;
         }          }
   
Line 913  trimthenstep6: Line 771  trimthenstep6:
          */           */
         todrop = (ti->ti_seq+ti->ti_len) - (tp->rcv_nxt+tp->rcv_wnd);          todrop = (ti->ti_seq+ti->ti_len) - (tp->rcv_nxt+tp->rcv_wnd);
         if (todrop > 0) {          if (todrop > 0) {
                 STAT(tcpstat.tcps_rcvpackafterwin++);  
                 if (todrop >= ti->ti_len) {                  if (todrop >= ti->ti_len) {
                         STAT(tcpstat.tcps_rcvbyteafterwin += ti->ti_len);  
                         /*                          /*
                          * If a new connection request is received                           * If a new connection request is received
                          * while in TIME_WAIT, drop the old connection                           * while in TIME_WAIT, drop the old connection
Line 938  trimthenstep6: Line 794  trimthenstep6:
                          */                           */
                         if (tp->rcv_wnd == 0 && ti->ti_seq == tp->rcv_nxt) {                          if (tp->rcv_wnd == 0 && ti->ti_seq == tp->rcv_nxt) {
                                 tp->t_flags |= TF_ACKNOW;                                  tp->t_flags |= TF_ACKNOW;
                                 STAT(tcpstat.tcps_rcvwinprobe++);                          } else {
                         } else  
                                 goto dropafterack;                                  goto dropafterack;
                 } else                          }
                         STAT(tcpstat.tcps_rcvbyteafterwin += todrop);                  }
                 m_adj(m, -todrop);                  m_adj(m, -todrop);
                 ti->ti_len -= todrop;                  ti->ti_len -= todrop;
                 tiflags &= ~(TH_PUSH|TH_FIN);                  tiflags &= ~(TH_PUSH|TH_FIN);
         }          }
   
         /*          /*
          * If last ACK falls within this segment's sequence numbers,  
          * record its timestamp.  
          */  
 /*      if (ts_present && SEQ_LEQ(ti->ti_seq, tp->last_ack_sent) &&  
  *          SEQ_LT(tp->last_ack_sent, ti->ti_seq + ti->ti_len +  
  *                 ((tiflags & (TH_SYN|TH_FIN)) != 0))) {  
  *              tp->ts_recent_age = tcp_now;  
  *              tp->ts_recent = ts_val;  
  *      }  
  */  
   
         /*  
          * If the RST bit is set examine the state:           * If the RST bit is set examine the state:
          *    SYN_RECEIVED STATE:           *    SYN_RECEIVED STATE:
          *      If passive open, return to LISTEN state.           *      If passive open, return to LISTEN state.
Line 973  trimthenstep6: Line 816  trimthenstep6:
         if (tiflags&TH_RST) switch (tp->t_state) {          if (tiflags&TH_RST) switch (tp->t_state) {
   
         case TCPS_SYN_RECEIVED:          case TCPS_SYN_RECEIVED:
 /*              so->so_error = ECONNREFUSED; */  
                 goto close;  
   
         case TCPS_ESTABLISHED:          case TCPS_ESTABLISHED:
         case TCPS_FIN_WAIT_1:          case TCPS_FIN_WAIT_1:
         case TCPS_FIN_WAIT_2:          case TCPS_FIN_WAIT_2:
         case TCPS_CLOSE_WAIT:          case TCPS_CLOSE_WAIT:
 /*              so->so_error = ECONNRESET; */  
         close:  
                 tp->t_state = TCPS_CLOSED;                  tp->t_state = TCPS_CLOSED;
                 STAT(tcpstat.tcps_drops++);  
                 tp = tcp_close(tp);                  tp = tcp_close(tp);
                 goto drop;                  goto drop;
   
Line 1022  trimthenstep6: Line 859  trimthenstep6:
                 if (SEQ_GT(tp->snd_una, ti->ti_ack) ||                  if (SEQ_GT(tp->snd_una, ti->ti_ack) ||
                     SEQ_GT(ti->ti_ack, tp->snd_max))                      SEQ_GT(ti->ti_ack, tp->snd_max))
                         goto dropwithreset;                          goto dropwithreset;
                 STAT(tcpstat.tcps_connects++);  
                 tp->t_state = TCPS_ESTABLISHED;                  tp->t_state = TCPS_ESTABLISHED;
                 /*                  /*
                  * The sent SYN is ack'ed with our sequence number +1                   * The sent SYN is ack'ed with our sequence number +1
Line 1039  trimthenstep6: Line 875  trimthenstep6:
                     soisfconnected(so);                      soisfconnected(so);
                     so->so_state &= ~SS_CTL;   /* success XXX */                      so->so_state &= ~SS_CTL;   /* success XXX */
                   } else if (ret == 2) {                    } else if (ret == 2) {
                     so->so_state = SS_NOFDREF; /* CTL_CMD */                      so->so_state &= SS_PERSISTENT_MASK;
                       so->so_state |= SS_NOFDREF; /* CTL_CMD */
                   } else {                    } else {
                     needoutput = 1;                      needoutput = 1;
                     tp->t_state = TCPS_FIN_WAIT_1;                      tp->t_state = TCPS_FIN_WAIT_1;
Line 1048  trimthenstep6: Line 885  trimthenstep6:
                   soisfconnected(so);                    soisfconnected(so);
                 }                  }
   
                 /* Do window scaling? */  
 /*              if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==  
  *                      (TF_RCVD_SCALE|TF_REQ_SCALE)) {  
  *                      tp->snd_scale = tp->requested_s_scale;  
  *                      tp->rcv_scale = tp->request_r_scale;  
  *              }  
  */  
                 (void) tcp_reass(tp, (struct tcpiphdr *)0, (struct mbuf *)0);                  (void) tcp_reass(tp, (struct tcpiphdr *)0, (struct mbuf *)0);
                 tp->snd_wl1 = ti->ti_seq - 1;                  tp->snd_wl1 = ti->ti_seq - 1;
                 /* Avoid ack processing; snd_una==ti_ack  =>  dup ack */                  /* Avoid ack processing; snd_una==ti_ack  =>  dup ack */
Line 1079  trimthenstep6: Line 909  trimthenstep6:
   
                 if (SEQ_LEQ(ti->ti_ack, tp->snd_una)) {                  if (SEQ_LEQ(ti->ti_ack, tp->snd_una)) {
                         if (ti->ti_len == 0 && tiwin == tp->snd_wnd) {                          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));                                        (long )m, (long )so));
                                 /*                                  /*
Line 1147  trimthenstep6: Line 976  trimthenstep6:
                         tp->snd_cwnd = tp->snd_ssthresh;                          tp->snd_cwnd = tp->snd_ssthresh;
                 tp->t_dupacks = 0;                  tp->t_dupacks = 0;
                 if (SEQ_GT(ti->ti_ack, tp->snd_max)) {                  if (SEQ_GT(ti->ti_ack, tp->snd_max)) {
                         STAT(tcpstat.tcps_rcvacktoomuch++);  
                         goto dropafterack;                          goto dropafterack;
                 }                  }
                 acked = ti->ti_ack - tp->snd_una;                  acked = ti->ti_ack - tp->snd_una;
                 STAT(tcpstat.tcps_rcvackpack++);  
                 STAT(tcpstat.tcps_rcvackbyte += acked);  
   
                 /*                  /*
                  * If we have a timestamp reply, update smoothed                   * If transmit timer is running and timed sequence
                  * round trip time.  If no timestamp is present but  
                  * transmit timer is running and timed sequence  
                  * number was acked, update smoothed round trip time.                   * number was acked, update smoothed round trip time.
                  * Since we now have an rtt measurement, cancel the                   * Since we now have an rtt measurement, cancel the
                  * timer backoff (cf., Phil Karn's retransmit alg.).                   * timer backoff (cf., Phil Karn's retransmit alg.).
                  * Recompute the initial retransmit timer.                   * Recompute the initial retransmit timer.
                  */                   */
 /*              if (ts_present)                  if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq))
  *                      tcp_xmit_timer(tp, tcp_now-ts_ecr+1);  
  *              else  
  */  
                      if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq))  
                         tcp_xmit_timer(tp,tp->t_rtt);                          tcp_xmit_timer(tp,tp->t_rtt);
   
                 /*                  /*
Line 1205  trimthenstep6: Line 1025  trimthenstep6:
                         tp->snd_wnd -= acked;                          tp->snd_wnd -= acked;
                         ourfinisacked = 0;                          ourfinisacked = 0;
                 }                  }
                 /*  
                  * XXX sowwakup is called when data is acked and there's room for  
                  * for more data... it should read() the socket  
                  */  
 /*              if (so->so_snd.sb_flags & SB_NOTIFY)  
  *                      sowwakeup(so);  
  */  
                 tp->snd_una = ti->ti_ack;                  tp->snd_una = ti->ti_ack;
                 if (SEQ_LT(tp->snd_nxt, tp->snd_una))                  if (SEQ_LT(tp->snd_nxt, tp->snd_una))
                         tp->snd_nxt = tp->snd_una;                          tp->snd_nxt = tp->snd_una;
Line 1233  trimthenstep6: Line 1046  trimthenstep6:
                                  * we'll hang forever.                                   * we'll hang forever.
                                  */                                   */
                                 if (so->so_state & SS_FCANTRCVMORE) {                                  if (so->so_state & SS_FCANTRCVMORE) {
                                         soisfdisconnected(so);  
                                         tp->t_timer[TCPT_2MSL] = TCP_MAXIDLE;                                          tp->t_timer[TCPT_2MSL] = TCP_MAXIDLE;
                                 }                                  }
                                 tp->t_state = TCPS_FIN_WAIT_2;                                  tp->t_state = TCPS_FIN_WAIT_2;
Line 1251  trimthenstep6: Line 1063  trimthenstep6:
                                 tp->t_state = TCPS_TIME_WAIT;                                  tp->t_state = TCPS_TIME_WAIT;
                                 tcp_canceltimers(tp);                                  tcp_canceltimers(tp);
                                 tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;                                  tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
                                 soisfdisconnected(so);  
                         }                          }
                         break;                          break;
   
Line 1288  step6: Line 1099  step6:
             (SEQ_LT(tp->snd_wl1, ti->ti_seq) ||              (SEQ_LT(tp->snd_wl1, ti->ti_seq) ||
             (tp->snd_wl1 == ti->ti_seq && (SEQ_LT(tp->snd_wl2, ti->ti_ack) ||              (tp->snd_wl1 == ti->ti_seq && (SEQ_LT(tp->snd_wl2, ti->ti_ack) ||
             (tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd))))) {              (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_wnd = tiwin;
                 tp->snd_wl1 = ti->ti_seq;                  tp->snd_wl1 = ti->ti_seq;
                 tp->snd_wl2 = ti->ti_ack;                  tp->snd_wl2 = ti->ti_ack;
Line 1384  dodata: Line 1191  dodata:
                          * will got to TCPS_LAST_ACK, and use tcp_output()                           * will got to TCPS_LAST_ACK, and use tcp_output()
                          * to send the FIN.                           * to send the FIN.
                          */                           */
 /*                      sofcantrcvmore(so); */  
                         sofwdrain(so);                          sofwdrain(so);
   
                         tp->t_flags |= TF_ACKNOW;                          tp->t_flags |= TF_ACKNOW;
Line 1421  dodata: Line 1227  dodata:
                         tp->t_state = TCPS_TIME_WAIT;                          tp->t_state = TCPS_TIME_WAIT;
                         tcp_canceltimers(tp);                          tcp_canceltimers(tp);
                         tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;                          tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
                         soisfdisconnected(so);  
                         break;                          break;
   
                 /*                  /*
Line 1440  dodata: Line 1245  dodata:
          *           *
          * See above.           * See above.
          */           */
 /*      if (ti->ti_len && (unsigned)ti->ti_len < tp->t_maxseg) {  
  */  
 /*      if ((ti->ti_len && (unsigned)ti->ti_len < tp->t_maxseg &&  
  *              (so->so_iptos & IPTOS_LOWDELAY) == 0) ||  
  *             ((so->so_iptos & IPTOS_LOWDELAY) &&  
  *             ((struct tcpiphdr_2 *)ti)->first_char == (char)27)) {  
  */  
         if (ti->ti_len && (unsigned)ti->ti_len <= 5 &&          if (ti->ti_len && (unsigned)ti->ti_len <= 5 &&
             ((struct tcpiphdr_2 *)ti)->first_char == (char)27) {              ((struct tcpiphdr_2 *)ti)->first_char == (char)27) {
                 tp->t_flags |= TF_ACKNOW;                  tp->t_flags |= TF_ACKNOW;
Line 1493  drop: Line 1291  drop:
         return;          return;
 }  }
   
  /* , ts_present, ts_val, ts_ecr) */  
 /*      int *ts_present;  
  *      u_int32_t *ts_val, *ts_ecr;  
  */  
 static void  static void
 tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt, struct tcpiphdr *ti)  tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt, struct tcpiphdr *ti)
 {  {
Line 1531  tcp_dooptions(struct tcpcb *tp, u_char * Line 1325  tcp_dooptions(struct tcpcb *tp, u_char *
                         NTOHS(mss);                          NTOHS(mss);
                         (void) tcp_mss(tp, mss);        /* sets t_maxseg */                          (void) tcp_mss(tp, mss);        /* sets t_maxseg */
                         break;                          break;
   
 /*              case TCPOPT_WINDOW:  
  *                      if (optlen != TCPOLEN_WINDOW)  
  *                              continue;  
  *                      if (!(ti->ti_flags & TH_SYN))  
  *                              continue;  
  *                      tp->t_flags |= TF_RCVD_SCALE;  
  *                      tp->requested_s_scale = min(cp[2], TCP_MAX_WINSHIFT);  
  *                      break;  
  */  
 /*              case TCPOPT_TIMESTAMP:  
  *                      if (optlen != TCPOLEN_TIMESTAMP)  
  *                              continue;  
  *                      *ts_present = 1;  
  *                      memcpy((char *) ts_val, (char *)cp + 2, sizeof(*ts_val));  
  *                      NTOHL(*ts_val);  
  *                      memcpy((char *) ts_ecr, (char *)cp + 6, sizeof(*ts_ecr));  
  *                      NTOHL(*ts_ecr);  
  *  
  */                     /*  
  *                       * A timestamp received in a SYN makes  
  *                       * it ok to send timestamp requests and replies.  
  *                       */  
 /*                      if (ti->ti_flags & TH_SYN) {  
  *                              tp->t_flags |= TF_RCVD_TSTMP;  
  *                              tp->ts_recent = *ts_val;  
  *                              tp->ts_recent_age = tcp_now;  
  *                      }  
  */                     break;  
                 }                  }
         }          }
 }  }
Line 1617  tcp_xmit_timer(register struct tcpcb *tp Line 1382  tcp_xmit_timer(register struct tcpcb *tp
         DEBUG_ARG("tp = %lx", (long)tp);          DEBUG_ARG("tp = %lx", (long)tp);
         DEBUG_ARG("rtt = %d", rtt);          DEBUG_ARG("rtt = %d", rtt);
   
         STAT(tcpstat.tcps_rttupdated++);  
         if (tp->t_srtt != 0) {          if (tp->t_srtt != 0) {
                 /*                  /*
                  * srtt is stored as fixed point with 3 bits after the                   * srtt is stored as fixed point with 3 bits after the
Line 1697  tcp_xmit_timer(register struct tcpcb *tp Line 1461  tcp_xmit_timer(register struct tcpcb *tp
  */   */
   
 int  int
 tcp_mss(tp, offer)  tcp_mss(struct tcpcb *tp, u_int offer)
         register struct tcpcb *tp;  
         u_int offer;  
 {  {
         struct socket *so = tp->t_socket;          struct socket *so = tp->t_socket;
         int mss;          int mss;

Removed from v.1.1.1.4  
changed lines
  Added in v.1.1.1.5


unix.superglobalmegacorp.com