home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / internet / tcpip / src205 / TCPIP_Src / TCP / c / tcpcmd next >
Encoding:
Text File  |  1995-03-22  |  11.5 KB  |  412 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <time.h>
  5. #include "global.h"
  6. #include "timer.h"
  7. #include "mbuf.h"
  8. #include "netuser.h"
  9. #include "internet.h"
  10. #include "tcp.h"
  11. #include "cmdparse.h"
  12. #include "misc.h"
  13. #include "arc.h"
  14. #include "asy.h"
  15.  
  16. #include "os.h"
  17. #include "swis.h"
  18.  
  19. static int dotcpreset(int, char **);
  20. static int dohangup(int, char **);
  21. static int doirtt(int, char **);
  22. static int dortt(int, char **);
  23. static int domrtt(int, char **);
  24. static int dotcpkick(int, char **);
  25. static int domss(int, char **);
  26. static int dowindow(int, char **);
  27. static int dotcpstat(int, char **);
  28. static int tstat(void);
  29. static void state_tcp(struct tcb *);
  30.  
  31. /* TCP connection states */
  32. char *tcpstates[] = {
  33.         "Closed",
  34.         "Listen",
  35.         "SYN sent",
  36.         "SYN received",
  37.         "Established",
  38.         "FIN wait 1",
  39.         "FIN wait 2",
  40.         "Close wait",
  41.         "Closing",
  42.         "Last ACK",
  43.         "Time wait"
  44. };
  45.  
  46. /* TCP closing reasons */
  47. char *reasons[] = {
  48.         "Normal",
  49.         "Reset",
  50.         "Timeout",
  51.         "ICMP"
  52. };
  53.  
  54. static struct timer busy;
  55. static int busy_checks = 0;
  56. static int busy_limit  = 0;
  57. static BOOL busy_exit  = FALSE;
  58.  
  59. /* TCP subcommand table */
  60. struct cmds tcpcmds[] = {
  61.         "hangup", dohangup,   3, "tcp hangup <check> <after> [exit]",  NULLCHAR,
  62.         "irtt",   doirtt,     1, "tcp irtt <val>",              NULLCHAR,
  63.         "kick",   dotcpkick,  2, "tcp kick <tcb>",              NULLCHAR,
  64.         "mss",    domss,      0, "tcp mss <val>",               NULLCHAR,
  65.         "mrtt",   domrtt,     1, "tcp mrtt <val>",              NULLCHAR,
  66.         "reset",  dotcpreset, 2, "tcp reset <tcb>",             NULLCHAR,
  67.         "rtt",    dortt,      3, "tcp rtt <tcb> <val>",         NULLCHAR,
  68.         "status", dotcpstat,  0, NULLCHAR,                      NULLCHAR,
  69.         "window", dowindow,   0, NULLCHAR,                      NULLCHAR,
  70.         NULLCHAR,
  71. };
  72. int dotcp(int argc, char **argv)
  73. {
  74.         return subcmd(tcpcmds,argc,argv);
  75. }
  76.  
  77. /* Eliminate a TCP connection */
  78. static int dotcpreset(int argc, char **argv)
  79. {
  80.         register struct tcb *tcb;
  81.         extern char notval[];
  82.  
  83.         argc = argc;
  84.  
  85.         tcb = (struct tcb *)htol(argv[1]);
  86.         if(!tcpval(tcb)){
  87.                 cwprintf(NULL, notval);
  88.                 return 1;
  89.         }
  90.         close_self(tcb,RESET);
  91.         return 0;
  92. }
  93.  
  94. int tcp_hasactive(void)
  95. {
  96.   register int i;
  97.   register struct tcb *tcb;
  98.  
  99.   for (i = 0; i < NTCB; i++)
  100.   {
  101.     for (tcb = tcbs[i]; tcb != NULLTCB; tcb = tcb->next)
  102.     {
  103.       if (tcb->state > 3 && tcb->state<10)
  104.         return 1;
  105.     }
  106.   }
  107.   return 0;
  108. }
  109.  
  110. static void dotcpbusy(void *p)
  111. {
  112.   p = p;
  113.   start_timer(&busy);
  114.  
  115.   if (tcp_hasactive())
  116.   {
  117.     busy_checks = 0;
  118.     return;
  119.   }
  120.   else
  121.     ++busy_checks;
  122.  
  123.   if (asy_scan())
  124.     cwprintf(NULL, "TCP checks clear = %d Hanging up after %d more\r\n", busy_checks, busy_limit - busy_checks);
  125.   else
  126.     busy_checks = 0;
  127.  
  128.   if (busy_checks == busy_limit)
  129.   {
  130.     iostop();
  131.     if (busy_exit)
  132.       net_exit();
  133.   }
  134. }
  135.  
  136. static int dohangup(int argc, char **argv)
  137. {
  138.   busy.func = dotcpbusy;
  139.   busy.arg = NULL;
  140.   busy_checks = 0;
  141.   busy_limit  = atoi(argv[2]);
  142.   cwprintf(NULL, "Check every %s seconds, hangup after %s clear checks\r\n", argv[1], argv[2]);
  143.   if (argc == 4 && strnicmp(argv[3], "exit", MIN(strlen(argv[3]), 4)) == 0)
  144.   {
  145.     busy_exit = TRUE;
  146.     cwprintf(NULL, "and exit program.\r\n");
  147.   }
  148.   if (busy_limit > 0)
  149.   {
  150.     set_timer(&busy, atol(argv[1]) * 1000L);
  151.     start_timer(&busy);
  152.   }
  153.   else
  154.   {
  155.     stop_timer(&busy);
  156.   }
  157.  
  158.   return(0);
  159. }
  160.  
  161. /* Set initial round trip time for new connections */
  162. static int doirtt(int argc, char **argv)
  163. {
  164.         if(argc < 2)
  165.                 cwprintf(NULL, "%lu\r\n",tcp_irtt);
  166.         else
  167.                 tcp_irtt = atol(argv[1]);
  168.         return 0;
  169. }
  170.  
  171. /* Set maximum round trip time for new connections */
  172. static int domrtt(int argc, char **argv)
  173. {
  174.         if(argc < 2)
  175.                 cwprintf(NULL, "%lu\r\n",tcp_mrtt*MSPTICK);
  176.         else
  177.                 tcp_mrtt = atol(argv[1])/MSPTICK;
  178.         return 0;
  179. }
  180.  
  181. /* Set smoothed round trip time for specified TCB */
  182. static int dortt(int argc, char **argv)
  183. {
  184.         register struct tcb *tcb;
  185.         extern char notval[];
  186.  
  187.         argc = argc;
  188.  
  189.         tcb = (struct tcb *)htol(argv[1]);
  190.         if(!tcpval(tcb)){
  191.                 cwprintf(NULL, notval);
  192.                 return 1;
  193.         }
  194.         tcb->srtt = atol(argv[2]);
  195.         return 0;
  196. }
  197.  
  198. /* Force a retransmission */
  199. static int dotcpkick(int argc, char **argv)
  200. {
  201.         register struct tcb *tcb;
  202.         extern char notval[];
  203.  
  204.         argc = argc;
  205.  
  206.         tcb = (struct tcb *)htol(argv[1]);
  207.         if(kick_tcp(tcb) == -1){
  208.                 cwprintf(NULL, notval);
  209.                 return 1;
  210.         }
  211.         return 0;
  212. }
  213.  
  214. /* Set default maximum segment size */
  215. static int domss(int argc, char **argv)
  216. {
  217.         if(argc < 2)
  218.                 cwprintf(NULL, "%u\r\n",tcp_mss);
  219.         else
  220.                 tcp_mss = atoi(argv[1]);
  221.         return 0;
  222. }
  223.  
  224. /* Set default window size */
  225. static int dowindow(int argc, char **argv)
  226. {
  227.         if(argc < 2)
  228.                 cwprintf(NULL, "%u\r\n",tcp_window);
  229.         else
  230.                 tcp_window = atoi(argv[1]);
  231.         return 0;
  232. }
  233.  
  234. /* Display status of TCBs */
  235. static int dotcpstat(int argc, char **argv)
  236. {
  237.         register struct tcb *tcb;
  238.         extern char notval[];
  239.  
  240.         if(argc < 2){
  241.                 tstat();
  242.         } else {
  243.                 tcb = (struct tcb *)htol(argv[1]);
  244.                 if(tcpval(tcb))
  245.                         state_tcp(tcb);
  246.                 else
  247.                         cwprintf(NULL, notval);
  248.         }
  249.         return 0;
  250. }
  251.  
  252. /* Dump TCP stats and summary of all TCBs
  253.  *     &TCB Rcv-Q Snd-Q  Local socket           Remote socket          State
  254.  *     1234     0     0  xxx.xxx.xxx.xxx:xxxxx  xxx.xxx.xxx.xxx:xxxxx  Established
  255.  
  256.  */
  257. static int tstat(void)
  258. {
  259.   extern char hostname[];
  260.   register int i;
  261.   register struct tcb *tcb;
  262.  
  263.   cwprintf(NULL, "Local site: %s\n", hostname);
  264.   cwprintf(NULL, "conout %u conin %u reset out %u runt %u chksum err %u bdcsts %u\r\n",
  265.           tcp_stat.conout,tcp_stat.conin,tcp_stat.resets,tcp_stat.runt,
  266.           tcp_stat.checksum,tcp_stat.bdcsts);
  267.   cwprintf(NULL, "    &TCB Rcv-Q Snd-Q  Local socket   Remote socket                State\r\n");
  268.   for (i = 0; i < NTCB; i++)
  269.   {
  270.     for (tcb = tcbs[i]; tcb != NULLTCB; tcb = tcb->next)
  271.     {
  272.       cwprintf(NULL, "%8lx%6u%6u  ", (long) tcb, tcb->rcvcnt, tcb->sndcnt);
  273.       cwprintf(NULL, "%-15s",tcp_port(tcb->conn.local.port));
  274.       cwprintf(NULL, "%-30s",psocket(&tcb->conn.remote));
  275.       cwprintf(NULL, "%-s",tcpstates[tcb->state]);
  276.       if (tcb->state == LISTEN && (tcb->flags & CLONE))
  277.         cwprintf(NULL, " (S)");
  278.       cwprintf(NULL, "\r\n");
  279.     }
  280.   }
  281.   return(0);
  282. }
  283. /*
  284. static int tstat(void)
  285. {
  286.         register int i;
  287.         register struct tcb *tcb;
  288.  
  289.         cwprintf(NULL, "conout %u conin %u reset out %u runt %u chksum err %u bdcsts %u\r\n",
  290.                 tcp_stat.conout,tcp_stat.conin,tcp_stat.resets,tcp_stat.runt,
  291.                 tcp_stat.checksum,tcp_stat.bdcsts);
  292.         cwprintf(NULL, "  &TCB Rcv-Q Snd-Q  Local socket            Remote socket           State\r\n");
  293.         for(i=0;i<NTCB;i++){
  294.                 for(tcb=tcbs[i];tcb != NULLTCB;tcb = tcb->next){
  295.                         cwprintf(NULL, "%6lx%6u%6u  ",(long)tcb,tcb->rcvcnt,tcb->sndcnt);
  296.                         cwprintf(NULL, "%-24s",psocket(&tcb->conn.local));
  297.                         cwprintf(NULL, "%-24s",psocket(&tcb->conn.remote));
  298.                         cwprintf(NULL, "%-s",tcpstates[tcb->state]);
  299.                         if(tcb->state == LISTEN && (tcb->flags & CLONE))
  300.                                 cwprintf(NULL, " (S)");
  301.                         cwprintf(NULL, "\r\n");
  302.                 }
  303.         }
  304.         return 0;
  305. }
  306. */
  307. /* Dump a TCP control block in detail */
  308. static void state_tcp(struct tcb *tcb)
  309. {
  310.         int32 sent,recvd;
  311.  
  312.         if(tcb == NULLTCB)
  313.                 return;
  314.         /* Compute total data sent and received; take out SYN and FIN */
  315.         sent = tcb->snd.una - tcb->iss; /* Acknowledged data only */
  316.         recvd = tcb->rcv.nxt - tcb->irs;
  317.         switch(tcb->state){
  318.         case LISTEN:
  319.         case SYN_SENT:          /* Nothing received or acked yet */
  320.                 sent = recvd = 0;
  321.                 break;
  322.         case SYN_RECEIVED:
  323.                 recvd--;        /* Got SYN, no data acked yet */
  324.                 sent = 0;
  325.                 break;
  326.         case ESTABLISHED:       /* Got and sent SYN */
  327.         case FINWAIT1:          /* FIN not acked yet */
  328.                 sent--;
  329.                 recvd--;
  330.                 break;
  331.         case FINWAIT2:          /* Our SYN and FIN both acked */
  332.                 sent -= 2;
  333.                 recvd--;
  334.                 break;
  335.         case CLOSE_WAIT:        /* Got SYN and FIN, our FIN not yet acked */
  336.         case CLOSING:
  337.         case LAST_ACK:
  338.                 sent--;
  339.                 recvd -= 2;
  340.                 break;
  341.         case TIME_WAIT:         /* Sent and received SYN/FIN, all acked */
  342.                 sent -= 2;
  343.                 recvd -= 2;
  344.                 break;
  345.         }
  346.         cwprintf(NULL, "Local: %s",psocket(&tcb->conn.local));
  347.         cwprintf(NULL, " Remote: %s",psocket(&tcb->conn.remote));
  348.         cwprintf(NULL, " State: %s\r\n",tcpstates[tcb->state]);
  349.         cwprintf(NULL, "      Init seq    Unack     Next Resent CWind Thrsh  Wind  MSS Queue      Total\r\n");
  350.         cwprintf(NULL, "Send:");
  351.         cwprintf(NULL, "%9lx",tcb->iss);
  352.         cwprintf(NULL, "%9lx",tcb->snd.una);
  353.         cwprintf(NULL, "%9lx",tcb->snd.nxt);
  354.         cwprintf(NULL, "%7lu",tcb->resent);
  355.         cwprintf(NULL, "%6u",tcb->cwind);
  356.         cwprintf(NULL, "%6u",tcb->ssthresh);
  357.         cwprintf(NULL, "%6u",tcb->snd.wnd);
  358.         cwprintf(NULL, "%5u",tcb->mss);
  359.         cwprintf(NULL, "%6u",tcb->sndcnt);
  360.         cwprintf(NULL, "%11lu\r\n",sent);
  361.  
  362.         cwprintf(NULL, "Recv:");
  363.         cwprintf(NULL, "%9lx",tcb->irs);
  364.         cwprintf(NULL, "         ");
  365.         cwprintf(NULL, "%9lx",tcb->rcv.nxt);
  366.         cwprintf(NULL, "%7lu",tcb->rerecv);
  367.         cwprintf(NULL, "      ");
  368.         cwprintf(NULL, "      ");
  369.         cwprintf(NULL, "%6u",tcb->rcv.wnd);
  370.         cwprintf(NULL, "     ");
  371.         cwprintf(NULL, "%6u",tcb->rcvcnt);
  372.         cwprintf(NULL, "%11lu\r\n",recvd);
  373.  
  374.         if(tcb->reseq != (struct reseq *)NULL){
  375.                 register struct reseq *rp;
  376.  
  377.                 cwprintf(NULL, "Reassembly queue:\r\n");
  378.                 for(rp = tcb->reseq;rp != (struct reseq *)NULL; rp = rp->next){
  379.                         cwprintf(NULL, "  seq x%lx %u bytes\r\n",rp->seg.seq,rp->length);
  380.                 }
  381.         }
  382.         if(tcb->backoff > 0)
  383.                 cwprintf(NULL, "Backoff %u ",tcb->backoff);
  384.         if(tcb->flags & RETRAN)
  385.                 cwprintf(NULL, "Retrying ");
  386.         switch(tcb->timer.state){
  387.         case TIMER_STOP:
  388.                 cwprintf(NULL, "Timer stopped ");
  389.                 break;
  390.         case TIMER_RUN:
  391.                 cwprintf(NULL, "Timer running (%ld/%ld ms) ",
  392.                  (long)MSPTICK * (tcb->timer.start - tcb->timer.count),
  393.                  (long)MSPTICK * tcb->timer.start);
  394.                 break;
  395.         case TIMER_EXPIRE:
  396.                 cwprintf(NULL, "Timer expired ");
  397.         }
  398.         cwprintf(NULL, "SRTT %ld ms Mean dev %ld ms\r\n",tcb->srtt,tcb->mdev);
  399. }
  400.  
  401. int rem_kick(void)
  402. {
  403.         register int i;
  404.         register struct tcb *tcb;
  405.         for(i=0;i<NTCB;i++){
  406.                 for(tcb=tcbs[i];tcb != NULLTCB;tcb = tcb->next){
  407.                         kick_tcp(tcb);
  408.                 }
  409.         }
  410.         return 0;
  411. }
  412.