home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 3 / hamradioversion3.0examsandprograms1992.iso / packet / n17jsrc / tcpcmd.c < prev    next >
C/C++ Source or Header  |  1991-04-29  |  8KB  |  350 lines

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