home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / network / src_1218.zip / TCPCMD.C < prev    next >
C/C++ Source or Header  |  1991-12-16  |  7KB  |  316 lines

  1. /* TCP control and status routines
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4. #include <stdio.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 "commands.h"
  13.  
  14. static int doirtt __ARGS((int argc,char *argv[],void *p));
  15. static int domss __ARGS((int argc,char *argv[],void *p));
  16. static int dortt __ARGS((int argc,char *argv[],void *p));
  17. static int dotcpkick __ARGS((int argc,char *argv[],void *p));
  18. static int dotcpreset __ARGS((int argc,char *argv[],void *p));
  19. static int dotcpstat __ARGS((int argc,char *argv[],void *p));
  20. static int dotcptr __ARGS((int argc,char *argv[],void *p));
  21. static int dowindow __ARGS((int argc,char *argv[],void *p));
  22. static int dosyndata __ARGS((int argc,char *argv[],void *p));
  23. static int tstat __ARGS((void));
  24.  
  25. /* TCP subcommand table */
  26. static struct cmds Tcpcmds[] = {
  27.     "irtt",        doirtt,        0, 0,    NULLCHAR,
  28.     "kick",        dotcpkick,    0, 2,    "tcp kick <tcb>",
  29.     "mss",        domss,        0, 0,    NULLCHAR,
  30.     "reset",    dotcpreset,    0, 2,    "tcp reset <tcb>",
  31.     "rtt",        dortt,        0, 3,    "tcp rtt <tcb> <val>",
  32.     "status",    dotcpstat,    0, 0,    NULLCHAR,
  33.     "syndata",    dosyndata,    0, 0,    NULLCHAR,
  34.     "trace",    dotcptr,    0, 0,    NULLCHAR,
  35.     "window",    dowindow,    0, 0,    NULLCHAR,
  36.     NULLCHAR,
  37. };
  38. int
  39. dotcp(argc,argv,p)
  40. int argc;
  41. char *argv[];
  42. void *p;
  43. {
  44.     return subcmd(Tcpcmds,argc,argv,p);
  45. }
  46. static int
  47. dotcptr(argc,argv,p)
  48. int argc;
  49. char *argv[];
  50. void *p;
  51. {
  52.     return setbool(&Tcp_trace,"TCP state tracing",argc,argv);
  53. }
  54.  
  55. /* Eliminate a TCP connection */
  56. static int
  57. dotcpreset(argc,argv,p)
  58. int argc;
  59. char *argv[];
  60. void *p;
  61. {
  62.     register struct tcb *tcb;
  63.  
  64.     tcb = (struct tcb *)ltop(htol(argv[1]));
  65.     if(!tcpval(tcb)){
  66.         tprintf(Notval);
  67.         return 1;
  68.     }
  69.     reset_tcp(tcb);
  70.     return 0;
  71. }
  72.  
  73. /* Set initial round trip time for new connections */
  74. static int
  75. doirtt(argc,argv,p)
  76. int argc;
  77. char *argv[];
  78. void *p;
  79. {
  80.     struct tcp_rtt *tp;
  81.  
  82.     setlong(&Tcp_irtt,"TCP default irtt",argc,argv);
  83.     if(argc < 2){
  84.         for(tp = &Tcp_rtt[0];tp < &Tcp_rtt[RTTCACHE];tp++){
  85.             if(tp->addr != 0){
  86.                 if(tprintf("%s: srtt %lu mdev %lu\n",
  87.                  inet_ntoa(tp->addr),
  88.                  tp->srtt,tp->mdev) == EOF)
  89.                     break;
  90.             }
  91.         }
  92.     }
  93.     return 0;
  94. }
  95.  
  96. /* Set smoothed round trip time for specified TCB */
  97. static int
  98. dortt(argc,argv,p)
  99. int argc;
  100. char *argv[];
  101. void *p;
  102. {
  103.     register struct tcb *tcb;
  104.  
  105.     tcb = (struct tcb *)ltop(htol(argv[1]));
  106.     if(!tcpval(tcb)){
  107.         tprintf(Notval);
  108.         return 1;
  109.     }
  110.     tcb->srtt = atol(argv[2]);
  111.     return 0;
  112. }
  113.  
  114. /* Force a retransmission */
  115. static int
  116. dotcpkick(argc,argv,p)
  117. int argc;
  118. char *argv[];
  119. void *p;
  120. {
  121.     register struct tcb *tcb;
  122.  
  123.     tcb = (struct tcb *)ltop(htol(argv[1]));
  124.     if(kick_tcp(tcb) == -1){
  125.         tprintf(Notval);
  126.         return 1;
  127.     }
  128.     return 0;
  129. }
  130.  
  131. /* Set default maximum segment size */
  132. static int
  133. domss(argc,argv,p)
  134. int argc;
  135. char *argv[];
  136. void *p;
  137. {
  138.     return setshort(&Tcp_mss,"TCP MSS",argc,argv);
  139. }
  140.  
  141. /* Set default window size */
  142. static int
  143. dowindow(argc,argv,p)
  144. int argc;
  145. char *argv[];
  146. void *p;
  147. {
  148.     return setshort(&Tcp_window,"TCP window",argc,argv);    
  149. }
  150.  
  151. static int
  152. dosyndata(argc,argv,p)
  153. int argc;
  154. char *argv[];
  155. void *p;
  156. {
  157.     return setbool(&Tcp_syndata,"TCP syn+data piggybacking",argc,argv);
  158. }
  159.  
  160.  
  161. /* Display status of TCBs */
  162. static int
  163. dotcpstat(argc,argv,p)
  164. int argc;
  165. char *argv[];
  166. void *p;
  167. {
  168.     register struct tcb *tcb;
  169.  
  170.     if(argc < 2){
  171.         tstat();
  172.     } else {
  173.         tcb = (struct tcb *)ltop(htol(argv[1]));
  174.         if(tcpval(tcb))
  175.             st_tcp(tcb);
  176.         else
  177.             tprintf(Notval);
  178.     }
  179.     return 0;
  180. }
  181.  
  182. /* Dump TCP stats and summary of all TCBs
  183. /*     &TCB Rcv-Q Snd-Q  Local socket           Remote socket          State
  184.  *     1234     0     0  xxx.xxx.xxx.xxx:xxxxx  xxx.xxx.xxx.xxx:xxxxx  Established
  185.  */
  186. static int
  187. tstat()
  188. {
  189.     register int i;
  190.     register struct tcb *tcb;
  191.     int j;
  192.  
  193.     for(j=i=1;i<=NUMTCPMIB;i++){
  194.         if(Tcp_mib[i].name == NULLCHAR)
  195.             continue;
  196.         tprintf("(%2u)%-20s%10lu",i,Tcp_mib[i].name,
  197.          Tcp_mib[i].value.integer);
  198.         if(j++ % 2)
  199.             tprintf("     ");
  200.         else
  201.             tprintf("\n");
  202.     }
  203.     if((j % 2) == 0)
  204.         tprintf("\n");
  205.  
  206.     tprintf("    &TCB Rcv-Q Snd-Q  Local socket           Remote socket          State\n");
  207.     for(tcb=Tcbs;tcb != NULLTCB;tcb = tcb->next){
  208.         tprintf("%8lx%6u%6u  ",ptol(tcb),tcb->rcvcnt,tcb->sndcnt);
  209.         tprintf("%-23s",pinet(&tcb->conn.local));
  210.         tprintf("%-23s",pinet(&tcb->conn.remote));
  211.         tprintf("%-s",Tcpstates[tcb->state]);
  212.         if(tcb->state == TCP_LISTEN && tcb->flags.clone)
  213.             tprintf(" (S)");
  214.         if(tprintf("\n") == EOF)
  215.             return 0;
  216.     }
  217.     return 0;
  218. }
  219. /* Dump a TCP control block in detail */
  220. void
  221. st_tcp(tcb)
  222. struct tcb *tcb;
  223. {
  224.     int32 sent,recvd;
  225.  
  226.     if(tcb == NULLTCB)
  227.         return;
  228.     /* Compute total data sent and received; take out SYN and FIN */
  229.     sent = tcb->snd.una - tcb->iss;    /* Acknowledged data only */
  230.     recvd = tcb->rcv.nxt - tcb->irs;
  231.     switch(tcb->state){
  232.     case TCP_LISTEN:
  233.     case TCP_SYN_SENT:    /* Nothing received or acked yet */
  234.         sent = recvd = 0;    
  235.         break;
  236.     case TCP_SYN_RECEIVED:
  237.         recvd--;    /* Got SYN, no data acked yet */
  238.         sent = 0;
  239.         break;
  240.     case TCP_ESTABLISHED:    /* Got and sent SYN */
  241.     case TCP_FINWAIT1:    /* FIN not acked yet */
  242.         sent--;
  243.         recvd--;
  244.         break;
  245.     case TCP_FINWAIT2:    /* Our SYN and FIN both acked */
  246.         sent -= 2;
  247.         recvd--;
  248.         break;
  249.     case TCP_CLOSE_WAIT:    /* Got SYN and FIN, our FIN not yet acked */
  250.     case TCP_CLOSING:
  251.     case TCP_LAST_ACK:
  252.         sent--;
  253.         recvd -= 2;
  254.         break;
  255.     case TCP_TIME_WAIT:    /* Sent and received SYN/FIN, all acked */
  256.         sent -= 2;
  257.         recvd -= 2;
  258.         break;
  259.     }
  260.     tprintf("Local: %s",pinet(&tcb->conn.local));
  261.     tprintf(" Remote: %s",pinet(&tcb->conn.remote));
  262.     tprintf(" State: %s\n",Tcpstates[tcb->state]);
  263.     tprintf("      Init seq    Unack     Next Resent CWind Thrsh  Wind  MSS Queue      Total\n");
  264.     tprintf("Send:");
  265.     tprintf("%9lx",tcb->iss);
  266.     tprintf("%9lx",tcb->snd.una);
  267.     tprintf("%9lx",tcb->snd.nxt);
  268.     tprintf("%7lu",tcb->resent);
  269.     tprintf("%6u",tcb->cwind);
  270.     tprintf("%6u",tcb->ssthresh);
  271.     tprintf("%6u",tcb->snd.wnd);
  272.     tprintf("%5u",tcb->mss);
  273.     tprintf("%6u",tcb->sndcnt);
  274.     tprintf("%11lu\n",sent);
  275.  
  276.     tprintf("Recv:");
  277.     tprintf("%9lx",tcb->irs);
  278.     tprintf("         ");
  279.     tprintf("%9lx",tcb->rcv.nxt);
  280.     tprintf("%7lu",tcb->rerecv);
  281.     tprintf("      ");
  282.     tprintf("      ");
  283.     tprintf("%6u",tcb->rcv.wnd);
  284.     tprintf("     ");
  285.     tprintf("%6u",tcb->rcvcnt);
  286.     tprintf("%11lu\n",recvd);
  287.  
  288.     if(tcb->reseq != (struct reseq *)NULL){
  289.         register struct reseq *rp;
  290.  
  291.         tprintf("Reassembly queue:\n");
  292.         for(rp = tcb->reseq;rp != (struct reseq *)NULL; rp = rp->next){
  293.             if(tprintf("  seq x%lx %u bytes\n",
  294.              rp->seg.seq,rp->length) == EOF)
  295.                 return;
  296.         }
  297.     }
  298.     if(tcb->backoff > 0)
  299.         tprintf("Backoff %u ",tcb->backoff);
  300.     if(tcb->flags.retran)
  301.         tprintf("Retrying ");
  302.     switch(tcb->timer.state){
  303.     case TIMER_STOP:
  304.         tprintf("Timer stopped ");
  305.         break;
  306.     case TIMER_RUN:
  307.         tprintf("Timer running (%ld/%ld ms) ",
  308.          (long)read_timer(&tcb->timer),
  309.          (long)dur_timer(&tcb->timer));
  310.         break;
  311.     case TIMER_EXPIRE:
  312.         tprintf("Timer expired ");
  313.     }
  314.     tprintf("SRTT %ld ms Mean dev %ld ms\n",tcb->srtt,tcb->mdev);
  315. }
  316.