tcp.c

来自「mcf5307实验源代码」· C语言 代码 · 共 1,562 行 · 第 1/5 页

C
1,562
字号
    dll_update_lists(&buffer_list, &buffer_freelist);
    break;

    case SCWAIT:
      ackcheck (prt, p);
      if (!prt->in.contain)
      {
         prt->tcpout.t.flags = TFIN | TACK;

         Send_SYN_FIN(prt, 0);

         prt->state = SLAST;
      } /* end if */
      /* Drop the packet by placing it back on the buffer_freelist. */
      dll_update_lists(&buffer_list, &buffer_freelist);
      break;

    case SLAST:    /* check ack of FIN, or reset to see if we are done */
      if (ackcheck (prt, p) == NU_SUCCESS)
      {
          prt->state = SCLOSED;

#if SNMP_INCLUDED
          SNMP_tcpConnTableUpdate(SNMP_DELETE, SEST, prt->tcpout.i.ipsource,
                                  prt->in.port, prt->tcpout.i.ipdest,
                                  prt->out.port);
#endif

//		  sprintf(buffer,"closed 3:%u-%u",syntimes,++syntimes_add);
//		  __TextOut(10,300,12,buffer);

		  netputevent (CONCLASS, CONCLOSE, pnum);
          dll_update_lists(&buffer_list, &buffer_freelist);
          break;
      }

      if ((p->t.flags & TRESET)
          || ((uint32)longswap (p->t.ack) == (prt->out.nxt + 1)))
	  {
//		  sprintf(buffer,"closed 4:%u-%u",syntimes,++syntimes_add);
//		  __TextOut(10,300,12,buffer);

		  netputevent (CONCLASS, CONCLOSE, pnum);
		  prt->state = SCLOSED;

#if SNMP_INCLUDED
          SNMP_tcpConnTableUpdate(SNMP_DELETE, SEST, prt->tcpout.i.ipsource,
                                  prt->in.port, prt->tcpout.i.ipdest,
                                  prt->out.port);
#endif
      }

      /* Drop the packet by placing it back on the buffer_freelist. */
      dll_update_lists(&buffer_list, &buffer_freelist);
      break;

    case SFW1:  /* waiting for ACK of FIN */
      /* throw away data */
      ackcheck (prt, p);
      prt->in.nxt = longswap (p->t.seq) + tlen - hlen;
      if (p->t.flags & TRESET)
	  {
//					  sprintf(buffer,"closed 5:%u-%u",syntimes,++syntimes_add);
//				  __TextOut(10,300,12,buffer);

		  netputevent (CONCLASS, CONCLOSE, pnum);
          prt->state = SCLOSED;

#if SNMP_INCLUDED
          SNMP_tcpConnTableUpdate(SNMP_DELETE, SEST, prt->tcpout.i.ipsource,
                                  prt->in.port, prt->tcpout.i.ipdest,
                                  prt->out.port);
#endif
      }
      else
      if ((uint32)longswap (p->t.ack) != (prt->out.nxt + 1))
	  {
          if (p->t.flags & TFIN)  /* got FIN, no ACK for mine */
          {
              prt->in.nxt++;               /* account for FIN byte */
              prt->tcpout.t.ack = longswap (prt->in.nxt);
              prt->tcpout.t.flags = TACK;     /* final byte has no FIN flag */

              tcp_sendack (prt, 0);

              prt->state = SCLOSING;

              /* Free up any buffers that were received but not processed. */
              dll_cleanup(&prt->in.packet_list);
          } /* end if */
          else
          {
              prt->tcpout.t.ack = longswap (prt->in.nxt);
              prt->tcpout.t.flags = TACK | TFIN;

              /* Since we are already in SFW1 a FIN has already been sent.  So
                 don't call Send_SYN_FIN here.  That would create another packet
                 containing a FIN that would have a retransmit event associated
                 with it. */
              tcp_sendack (prt, 0);
          } /* end else */
	  } /* end if */
	  else
	    if (p->t.flags & TFIN)	/* ACK and FIN */
	    {
            prt->in.nxt++;               /* account for his FIN flag */
            prt->out.nxt++;              /* account for my FIN */
            prt->tcpout.t.ack = longswap (prt->in.nxt);
            prt->tcpout.t.flags = TACK;     /* final byte has no FIN flag */
            tcp_sendack (prt, 0);

//							  sprintf(buffer,"closed 6:%u-%u",syntimes,++syntimes_add);
//				  __TextOut(10,300,12,buffer);

			netputevent (CONCLASS, CONCLOSE, pnum);
            prt->state = STWAIT;    /* we are done */

#if SNMP_INCLUDED
            SNMP_tcpConnTableUpdate(SNMP_DELETE, SEST, prt->tcpout.i.ipsource,
                                    prt->in.port, prt->tcpout.i.ipdest,
                                    prt->out.port);
#endif

            /* Free up any buffers that were received but not processed. */
            dll_cleanup(&prt->in.packet_list);
        } /* end if */
	    else
	    {	   /* got ACK, no FIN */
            prt->out.nxt++;              /* account for my FIN byte */
            prt->tcpout.t.flags = TACK;     /* final pkt has no FIN flag */
            prt->state = SFW2;
	    } /* end else */
      /* Drop the packet by placing it back on the buffer_freelist. */
      dll_update_lists(&buffer_list, &buffer_freelist);
      break;

    case SFW2:
      /* want FIN */
      ackcheck (prt, p);
      prt->in.nxt=longswap(p->t.seq)+tlen-hlen;
      if(p->t.flags&TRESET)
	  {
//					  sprintf(buffer,"closed 7:%u-%u",syntimes,++syntimes_add);
//				  __TextOut(10,300,12,buffer);

		  netputevent (CONCLASS, CONCLOSE, pnum);
          prt->state=SCLOSED;

#if SNMP_INCLUDED
          SNMP_tcpConnTableUpdate(SNMP_DELETE, SEST, prt->tcpout.i.ipsource,
                                  prt->in.port, prt->tcpout.i.ipdest,
                                  prt->out.port);
#endif

      }
      else
      if(p->t.flags&TFIN)   /* we got FIN */
      {
            prt->in.nxt++;                   /* count his FIN byte */
            prt->tcpout.t.ack=longswap(prt->in.nxt);
            tcp_sendack (prt, 0);

//							  sprintf(buffer,"closed 8:%u-%u",syntimes,++syntimes_add);
//				  __TextOut(10,300,12,buffer);

			netputevent(CONCLASS, CONCLOSE, pnum);
            prt->state=STWAIT;

#if SNMP_INCLUDED
            SNMP_tcpConnTableUpdate(SNMP_DELETE, SEST, prt->tcpout.i.ipsource,
                                    prt->in.port, prt->tcpout.i.ipdest,
                                    prt->out.port);
#endif

            /* Free up any buffers that were received but not processed. */
            dll_cleanup(&prt->in.packet_list);
      } /* end if */
      /* Drop the packet by placing it back on the buffer_freelist. */
      dll_update_lists(&buffer_list, &buffer_freelist);
      break;

    case SCLOSING:                        /* want ACK of FIN */
      if(p->t.flags&TRESET)
	  {
//					  sprintf(buffer,"closed 9:%u-%u",syntimes,++syntimes_add);
//				  __TextOut(10,300,12,buffer);

		  netputevent (CONCLASS, CONCLOSE, pnum);
          prt->state = SCLOSED;

#if SNMP_INCLUDED
          SNMP_tcpConnTableUpdate(SNMP_DELETE, SEST, prt->tcpout.i.ipsource,
                                  prt->in.port, prt->tcpout.i.ipdest,
                                  prt->out.port);
#endif

      }
      else if(!ackcheck(prt,p))
      {
		  prt->out.nxt++;              /* account for my FIN byte */
//						  sprintf(buffer,"closed 10:%u-%u",syntimes,++syntimes_add);
//				  __TextOut(10,300,12,buffer);

		  netputevent(CONCLASS, CONCLOSE, pnum);
          prt->state = STWAIT;       /* time-wait state next */

#if SNMP_INCLUDED
          SNMP_tcpConnTableUpdate(SNMP_DELETE, SEST, prt->tcpout.i.ipsource,
                                  prt->in.port, prt->tcpout.i.ipdest,
                                  prt->out.port);
#endif

      } /* end if */
      /* Drop the packet by placing it back on the buffer_freelist. */
      dll_update_lists(&buffer_list, &buffer_freelist);
      break;

    case STWAIT:                      /* ack FIN again? */
      if(p->t.flags&TRESET)
	  {
//					  sprintf(buffer,"closed 11:%u-%u",syntimes,++syntimes_add);
//				  __TextOut(10,300,12,buffer);

		  netputevent (CONCLASS, CONCLOSE, pnum);
          prt->state = SCLOSED;

#if SNMP_INCLUDED
          SNMP_tcpConnTableUpdate(SNMP_DELETE, SEST, prt->tcpout.i.ipsource,
                                  prt->in.port, prt->tcpout.i.ipdest,
                                  prt->out.port);
#endif

      }
      if(prt->out.lasttime &&
            (INT32_CMP(prt->out.lasttime+WAITTIME, n_clicks()) < 0)
            || p->t.flags&TFIN)          /* only if he wants it */
      {
         tcp_sendack (prt, 0);
         prt->state = SCLOSED;

#if SNMP_INCLUDED
          SNMP_tcpConnTableUpdate(SNMP_DELETE, SEST, prt->tcpout.i.ipsource,
                                  prt->in.port, prt->tcpout.i.ipdest,
                                  prt->out.port);
#endif

      }
      /* Drop the packet by placing it back on the buffer_freelist. */
      dll_update_lists(&buffer_list, &buffer_freelist);
      break;

    case SCLOSED:
        prt->in.port = prt->out.port = 0;
        for(ii = 0; ii < 4; ii++)
           prt->tcpout.i.ipdest[ii] = 0;
        /* Drop the packet by placing it back on the buffer_freelist. */
        dll_update_lists(&buffer_list, &buffer_freelist);
        break;

    default:
      NU_Tcp_Log_Error (TCP_UNKOWN_STATE, TCP_RECOVERABLE,
                         __FILE__, __LINE__);
      /* Drop the packet by placing it back on the buffer_freelist. */
      dll_update_lists(&buffer_list, &buffer_freelist);

      break;
  } /* end switch */

  return(0);
}   /* end tcpdo() */

/*************************************************************************/
/*                                                                       */
/* FUNCTION                                                              */
/*                                                                       */
/*      checkmss                                                         */
/*                                                                       */
/* DESCRIPTION                                                           */
/*                                                                       */
/*  Look at incoming SYN,ACK packet and check for the options field      */
/*  containing a TCP Maximum segment size option.  If it has one,        */
/*  then set the port's internal value to make sure that it never        */
/*  exceeds that segment size.                                           */
/*                                                                       */
/* CALLED BY                                                             */
/*      tcpdo                                                            */
/*                                                                       */
/* CALLS                                                                 */
/*                                                                       */
/*      intswap                                                          */
/*                                                                       */
/*************************************************************************/
static void checkmss(struct port *prt,TCPKT *p, uint16 hlen)
{
  uint16 i;

  /*  Check header for maximum segment size option.  */
  if(hlen > 20 && p->x.options[0] == 2 && p->x.options[1] == 4)
  {

    /* Copy the sender's negotiated value. */
    memcpy ( (void *)&i, (const void *)&p->x.options[2], 2);

    /* swapped value of maxseg */
    i=intswap(i);

    /* we have our own limits too */
    if(i < (uint16) (prt->sendsize))
      prt->sendsize=i;

  } /* end if */
}   /* end checkmss() */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?