home *** CD-ROM | disk | FTP | other *** search
/ The Pier Shareware 6 / The_Pier_Shareware_Number_6_(The_Pier_Exchange)_(1995).iso / 024 / psi110g.zip / TCPCMD.C < prev    next >
C/C++ Source or Header  |  1994-04-17  |  27KB  |  973 lines

  1. /* TCP control and status routines
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  *
  4.  * Mods by G1EMM
  5.  * Mods by WG7J
  6.  * Mods by WA3DSP
  7.  * Mods by PA0GRI
  8.  * Copyright 1992 Gerard J van der Grinten, PA0GRI
  9.  */
  10. #ifdef MSDOS
  11. #include <dos.h>
  12. #endif
  13. #include <ctype.h>
  14. #include "global.h"
  15. #include "timer.h"
  16. #include "mbuf.h"
  17. #include "netuser.h"
  18. #include "internet.h"
  19. #include "iface.h"
  20. #include "tcp.h"
  21. #include "cmdparse.h"
  22. #include "commands.h"
  23. #include "socket.h"
  24.   
  25. #ifdef  TCPACCESS
  26. static int doaccess __ARGS((int argc,char *argv[],void *p));
  27. void addtaccess __ARGS((int32 target,unsigned int bits,int16 low,int16 high,int16 permit));
  28. #endif
  29. static int tcpirtt __ARGS((int argc,char *argv[],void *p));
  30. static int dotcpirtt __ARGS((int argc,char *argv[],void *p));
  31. static int tcpmss __ARGS((int argc,char *argv[],void *p));
  32. static int dotcpmss __ARGS((int argc,char *argv[],void *p));
  33. static int dortt __ARGS((int argc,char *argv[],void *p));
  34. static int dotcpkick __ARGS((int argc,char *argv[],void *p));
  35. static int dotcpreset __ARGS((int argc,char *argv[],void *p));
  36. static int dotcpretries __ARGS((int argc,char *argv[],void *p));
  37. static int tcpretries __ARGS((int argc,char *argv[],void *p));
  38. static int dotcpstat __ARGS((int argc,char *argv[],void *p));
  39. static int dotcptimer __ARGS((int argc,char *argv[],void *p));
  40. static int tcptimer __ARGS((int argc,char *argv[],void *p));
  41. static int dotcptr __ARGS((int argc,char *argv[],void *p));
  42. static int dotcpwindow __ARGS((int argc,char *argv[],void *p));
  43. static int tcpwindow __ARGS((int argc,char *argv[],void *p));
  44. static int dotcpmaxwait __ARGS((int argc,char *argv[],void *p));
  45. static int tcpmaxwait __ARGS((int argc,char *argv[],void *p));
  46. static int dotcpsyndata __ARGS((int argc,char *argv[],void *p));
  47. static int tcpsyndata __ARGS((int argc,char *argv[],void *p));
  48. int doview __ARGS((int argc,char *argv[],void *p));
  49. static int dotcpblimit __ARGS((int argc,char *argv[],void *p));
  50. static int tcpblimit __ARGS((int argc,char *argv[],void *p));
  51. void rxtx_data_compute __ARGS((struct tcb *tcb,int32 *sent,int32 *recvd));
  52. #ifdef TCPACCESS
  53. struct rtaccess *TCPaccess = NULLACCESS; /* access list */
  54. #endif
  55.   
  56. /* TCP subcommand table */
  57. static struct cmds DFAR Tcpcmds[] = {
  58. #ifdef  TCPACCESS
  59.     "access",       doaccess,       0,      0, NULLCHAR,
  60. #endif
  61.     "blimit",       dotcpblimit,    0, 0,   NULLCHAR,
  62.     "irtt",         dotcpirtt,      0, 0,   NULLCHAR,
  63.     "kick",         dotcpkick,      0, 2,   "tcp kick <tcb>",
  64.     "maxwait",      dotcpmaxwait,   0, 0,   NULLCHAR,
  65.     "mss",          dotcpmss,       0, 0,   NULLCHAR,
  66.     "reset",        dotcpreset,     0, 2,   "tcp reset <tcb>",
  67.     "retries",      dotcpretries,   0,0,    NULLCHAR,
  68.     "rtt",          dortt,          0, 3,   "tcp rtt <tcb> <val>",
  69.     "status",       dotcpstat,      0, 0,   NULLCHAR,
  70.     "syndata",      dotcpsyndata,   0, 0,   NULLCHAR,
  71.     "timertype",    dotcptimer,     0, 0,   NULLCHAR,
  72.     "trace",        dotcptr,        0, 0,   NULLCHAR,
  73.     "view",         doview,         0, 0,   NULLCHAR,
  74.     "window",       dotcpwindow,    0, 0,   NULLCHAR,
  75.     NULLCHAR,
  76. };
  77. int
  78. dotcp(argc,argv,p)
  79. int argc;
  80. char *argv[];
  81. void *p;
  82. {
  83.     return subcmd(Tcpcmds,argc,argv,p);
  84. }
  85. static int
  86. dotcptr(argc,argv,p)
  87. int argc;
  88. char *argv[];
  89. void *p;
  90. {
  91.     return setbool(&Tcp_trace,"TCP state tracing",argc,argv);
  92. }
  93.   
  94. /* Eliminate a TCP connection */
  95. static int
  96. dotcpreset(argc,argv,p)
  97. int argc;
  98. char *argv[];
  99. void *p;
  100. {
  101.     register struct tcb *tcb;
  102.   
  103.     tcb = MK_FP(htoi(argv[1]),8);
  104.     if(!tcpval(tcb)){
  105.         tputs(Notval);
  106.         return 1;
  107.     }
  108.     reset_tcp(tcb);
  109.     return 0;
  110. }
  111.   
  112. /* Set initial round trip time for new connections */
  113. static int
  114. tcpirtt(argc,argv,p)
  115. int argc;
  116. char *argv[];
  117. void *p;
  118. {
  119.     return setlong((long *)p,"TCP default irtt",argc,argv);
  120. }
  121. static int
  122. dotcpirtt(argc,argv,p)
  123. int argc;
  124. char *argv[];
  125. void *p;
  126. {
  127.     struct tcp_rtt *tp;
  128.   
  129.     tcpirtt(argc,argv,(void *)&Tcp_irtt);
  130.     if(argc < 2){
  131.         for(tp = &Tcp_rtt[0];tp < &Tcp_rtt[RTTCACHE];tp++){
  132.             if(tp->addr != 0){
  133.                 if(tprintf("%s: srtt %lu mdev %lu\n",
  134.                     inet_ntoa(tp->addr),
  135.                     tp->srtt,tp->mdev) == EOF)
  136.                     break;
  137.             }
  138.         }
  139.     }
  140.     return 0;
  141. }
  142.   
  143. /* Set smoothed round trip time for specified TCB */
  144. static int
  145. dortt(argc,argv,p)
  146. int argc;
  147. char *argv[];
  148. void *p;
  149. {
  150.     register struct tcb *tcb;
  151.     tcb = MK_FP(htoi(argv[1]),8);
  152.     if(!tcpval(tcb)){
  153.         tputs(Notval);
  154.         return 1;
  155.     }
  156.     tcb->srtt = atol(argv[2]);
  157.     return 0;
  158. }
  159.   
  160. /* Force a retransmission */
  161. static int
  162. dotcpkick(argc,argv,p)
  163. int argc;
  164. char *argv[];
  165. void *p;
  166. {
  167.     register struct tcb *tcb;
  168.     tcb = MK_FP(htoi(argv[1]),8);
  169.     if(kick_tcp(tcb) == -1){
  170.         tputs(Notval);
  171.         return 1;
  172.     }
  173.     return 0;
  174. }
  175.   
  176. /* Set default maximum segment size */
  177. static int
  178. tcpmss(argc,argv,p)
  179. int argc;
  180. char *argv[];
  181. void *p;
  182. {
  183.     return setshort((unsigned short *)p,"TCP MSS",argc,argv);
  184. }
  185. static int
  186. dotcpmss(argc,argv,p)
  187. int argc;
  188. char *argv[];
  189. void *p;
  190. {
  191.     return tcpmss(argc,argv,(void *)&Tcp_mss);
  192. }
  193.   
  194. /* Set default window size */
  195. static int
  196. tcpwindow(argc,argv,p)
  197. int argc;
  198. char *argv[];
  199. void *p;
  200. {
  201.     return setshort((unsigned short *)p,"TCP window",argc,argv);
  202. }
  203. static int
  204. dotcpwindow(argc,argv,p)
  205. int argc;
  206. char *argv[];
  207. void *p;
  208. {
  209.     return tcpwindow(argc,argv,(void *)&Tcp_window);
  210. }
  211.   
  212. static int
  213. tcpsyndata(argc,argv,p)
  214. int argc;
  215. char *argv[];
  216. void *p;
  217. {
  218.     return setbool((int *)p,"TCP syn+data piggybacking",argc,argv);
  219. }
  220. static int
  221. dotcpsyndata(argc,argv,p)
  222. int argc;
  223. char *argv[];
  224. void *p;
  225. {
  226.     return tcpsyndata(argc,argv,(void *)&Tcp_syndata);
  227. }
  228.   
  229. extern int Tcp_retries;
  230.   
  231. /* Set maximum number of backoffs before resetting the connection */
  232. static int
  233. tcpretries(argc,argv,p)
  234. int argc;
  235. char *argv[];
  236. void *p;
  237. {
  238.     return setint((int *)p,"max. retries",argc,argv);
  239. }
  240. static int
  241. dotcpretries(argc,argv,p)
  242. int argc;
  243. char *argv[];
  244. void *p;
  245. {
  246.     return tcpretries(argc,argv,(void *)&Tcp_retries);
  247. }
  248.   
  249. extern long Tcp_maxwait;
  250.   
  251. /* Set maximum retry waittime in ms. */
  252. static int
  253. tcpmaxwait(argc,argv,p)
  254. int argc;
  255. char *argv[];
  256. void *p;
  257. {
  258.     return setlong((long *)p,"max. retry wait (ms)",argc,argv);
  259. }
  260. static int
  261. dotcpmaxwait(argc,argv,p)
  262. int argc;
  263. char *argv[];
  264. void *p;
  265. {
  266.     return tcpmaxwait(argc,argv,(void *)&Tcp_maxwait);
  267. }
  268.   
  269. extern int Tcp_blimit;
  270.   
  271. /* Set backoff limit on the connection; from N1BEE */
  272. static int
  273. tcpblimit(argc,argv,p)
  274. int argc;
  275. char *argv[];
  276. void *p;
  277. {
  278.     return setint((int *)p,"backoff limit",argc,argv);
  279. }
  280. static int
  281. dotcpblimit(argc,argv,p)
  282. int argc;
  283. char *argv[];
  284. void *p;
  285. {
  286.     return tcpblimit(argc,argv,(void *)&Tcp_blimit);
  287. }
  288.   
  289. #ifdef oldtcpstat
  290. static int tstat __ARGS((void));
  291.   
  292. /* Display status of TCBs */
  293. static int
  294. dotcpstat(argc,argv,p)
  295. int argc;
  296. char *argv[];
  297. void *p;
  298. {
  299.     register struct tcb *tcb;
  300.   
  301.     if(argc < 2){
  302.         tstat();
  303.     } else {
  304.   
  305.         tcb = MK_FP(htoi(argv[1]),8);
  306.         if(!tcpval(tcb))
  307.             tputs(Notval);
  308.         else
  309.             st_tcp(tcb);
  310.     }
  311.     return 0;
  312. }
  313.   
  314. /* Dump TCP stats and summary of all TCBs
  315.  *     &TCB Rcv-Q Snd-Q  Local socket           Remote socket          State
  316.  *     1234     0     0  xxx.xxx.xxx.xxx:xxxxx  xxx.xxx.xxx.xxx:xxxxx  Established
  317.  */
  318. static int
  319. tstat()
  320. {
  321.     register int i;
  322.     register struct tcb *tcb;
  323.     int j;
  324.   
  325.     for(j=i=1;i<=NUMTCPMIB;i++){
  326.         if(Tcp_mib[i].name == NULLCHAR)
  327.             continue;
  328.         tprintf("(%2u)%-20s%10lu",i,Tcp_mib[i].name,
  329.         Tcp_mib[i].value.integer);
  330.         if(j++ % 2)
  331.             tputs("     ");
  332.         else
  333.             tputc('\n');
  334.     }
  335.     if((j % 2) == 0)
  336.         tputc('\n');
  337.   
  338. #ifdef UNIX
  339.     tputs("&TCB     Rcv-Q Snd-Q  Local socket           Remote socket          State\n");
  340. #else
  341.     tputs("&TCB Rcv-Q Snd-Q  Local socket           Remote socket          State\n");
  342. #endif
  343.     for(tcb=Tcbs;tcb != NULLTCB;tcb = tcb->next){
  344. #ifdef UNIX
  345.         tprintf("%8.8x%6u%6u  ",FP_SEG(tcb),tcb->rcvcnt,tcb->sndcnt);
  346. #else
  347.         tprintf("%4.4x%6u%6u  ",FP_SEG(tcb),tcb->rcvcnt,tcb->sndcnt);
  348. #endif
  349.         tprintf("%-23s",pinet(&tcb->conn.local));
  350.         tprintf("%-23s",pinet(&tcb->conn.remote));
  351.         tprintf("%-s",Tcpstates[tcb->state]);
  352.         if(tcb->state == TCP_LISTEN && tcb->flags.clone)
  353.             tputs(" (S)");
  354.         if(tputc('\n') == EOF)
  355.             return 0;
  356.     }
  357.     return 0;
  358. }
  359.   
  360. #else
  361. /* New tcp stat by Doug Crompton, wa3dsp */
  362. static int tstat __ARGS((int flag));
  363.   
  364. /* Display status of TCBs */
  365. static int
  366. dotcpstat(argc,argv,p)
  367. int argc;
  368. char *argv[];
  369. void *p;
  370. {
  371.     struct tcb *tcb;
  372.   
  373.     if(argc < 2){
  374.         tstat(0);
  375.     } else {
  376.         if (toupper(argv[1][0])=='A') {
  377.             tstat(1);
  378.         } else {
  379.             tcb = MK_FP(htoi(argv[1]),8);
  380.             if(!tcpval(tcb))
  381.                 tputs(Notval);
  382.             else
  383.                 st_tcp(tcb);
  384.         }
  385.     }
  386.     return 0;
  387. }
  388.   
  389. /* Dump TCP stats and summary of all TCBs
  390.  *     &TCB Rcv-Q Snd-Q  Local socket           Remote socket          State
  391.  *     1234     0     0  xxx.xxx.xxx.xxx:xxxxx  xxx.xxx.xxx.xxx:xxxxx  Established
  392.  */
  393. static int
  394. tstat(int flag)
  395. {
  396.     int i;
  397.     struct tcb *tcb;
  398.     int j;
  399.   
  400.     for(j=i=1;i<=NUMTCPMIB;i++){
  401.         if(Tcp_mib[i].name == NULLCHAR)
  402.             continue;
  403.         tprintf("(%2u)%-20s%10lu",i,Tcp_mib[i].name,
  404.         Tcp_mib[i].value.integer);
  405.         if(j++ % 2)
  406.             tputs("     ");
  407.         else
  408.             tputs("\n");
  409.     }
  410.     if((j % 2) == 0)
  411.         tputs("\n");
  412.   
  413. #ifdef UNIX
  414.     tputs("&TCB     Rcv-Q Snd-Q  Local socket           Remote socket          State\n");
  415. #else
  416.     tputs("&TCB Rcv-Q Snd-Q  Local socket           Remote socket          State\n");
  417. #endif
  418.     for(tcb=Tcbs;tcb != NULLTCB;tcb = tcb->next){
  419.         if(tcb->state == TCP_LISTEN && !flag)
  420.             continue;
  421. #ifdef UNIX
  422.         tprintf("%8.8x%6u%6u  ",FP_SEG(tcb),tcb->rcvcnt,tcb->sndcnt);
  423. #else
  424.         tprintf("%4.4x%6u%6u  ",FP_SEG(tcb),tcb->rcvcnt,tcb->sndcnt);
  425. #endif
  426.         tprintf("%-23s",pinet(&tcb->conn.local));
  427.         tprintf("%-23s",pinet(&tcb->conn.remote));
  428.         tprintf("%-s",Tcpstates[tcb->state]);
  429.         if(tcb->state == TCP_LISTEN && tcb->flags.clone)
  430.             tputs(" (S)");
  431.         if(tputs("\n") == EOF)
  432.             return 0;
  433.     }
  434.     return 0;
  435. }
  436.   
  437. #endif
  438.   
  439. /* Dump a TCP control block in detail */
  440. void
  441. st_tcp(tcb)
  442. struct tcb *tcb;
  443. {
  444.     int32 sent,recvd;
  445.   
  446.     if(tcb == NULLTCB)
  447.         return;
  448.   
  449.     rxtx_data_compute(tcb,&sent,&recvd);
  450.   
  451.     tprintf("Local: %s",pinet(&tcb->conn.local));
  452.     tprintf(" Remote: %s",pinet(&tcb->conn.remote));
  453.     tprintf(" State: %s\n",Tcpstates[tcb->state]);
  454.     tputs("      Init seq    Unack     Next Resent CWind Thrsh  Wind  MSS Queue      Total\n"
  455.     "Send:");
  456.     tprintf("%9lx",tcb->iss);
  457.     tprintf("%9lx",tcb->snd.una);
  458.     tprintf("%9lx",tcb->snd.nxt);
  459.     tprintf("%7lu",tcb->resent);
  460.     tprintf("%6u",tcb->cwind);
  461.     tprintf("%6u",tcb->ssthresh);
  462.     tprintf("%6u",tcb->snd.wnd);
  463.     tprintf("%5u",tcb->mss);
  464.     tprintf("%6u",tcb->sndcnt);
  465.     tprintf("%11lu\n",sent);
  466.   
  467.     tputs("Recv:");
  468.     tprintf("%9lx",tcb->irs);
  469.     tputs("         ");
  470.     tprintf("%9lx",tcb->rcv.nxt);
  471.     tprintf("%7lu",tcb->rerecv);
  472.     tputs("      ");
  473.     tputs("      ");
  474.     tprintf("%6u",tcb->rcv.wnd);
  475.     tputs("     ");
  476.     tprintf("%6u",tcb->rcvcnt);
  477.     tprintf("%11lu\n",recvd);
  478.   
  479.     if(tcb->reseq != (struct reseq *)NULL){
  480.         register struct reseq *rp;
  481.   
  482.         tputs("Reassembly queue:\n");
  483.         for(rp = tcb->reseq;rp != (struct reseq *)NULL; rp = rp->next){
  484.             if(tprintf("  seq x%lx %u bytes\n",
  485.                 rp->seg.seq,rp->length) == EOF)
  486.                 return;
  487.         }
  488.     }
  489.     if(tcb->backoff > 0)
  490.         tprintf("Backoff %u ",tcb->backoff);
  491.     if(tcb->flags.retran)
  492.         tputs("Retrying ");
  493.     switch(tcb->timer.state){
  494.         case TIMER_STOP:
  495.             tputs("Timer stopped ");
  496.             break;
  497.         case TIMER_RUN:
  498.             tprintf("Timer running (%ld/%ld ms) ",
  499.             (long)read_timer(&tcb->timer),
  500.             (long)dur_timer(&tcb->timer));
  501.             break;
  502.         case TIMER_EXPIRE:
  503.             tputs("Timer expired ");
  504.     }
  505.     tprintf("SRTT %ld ms Mean dev %ld ms\n",tcb->srtt,tcb->mdev);
  506. }
  507.   
  508. void
  509. rxtx_data_compute(tcb,sent,recvd)
  510. struct tcb *tcb;
  511. int32 *sent;
  512. int32 *recvd;
  513. {
  514.   
  515.     /* Compute total data sent and received; take out SYN and FIN */
  516.     *sent = tcb->snd.una - tcb->iss;        /* Acknowledged data only */
  517.     *recvd = tcb->rcv.nxt - tcb->irs;
  518.     switch(tcb->state){
  519.         case TCP_LISTEN:
  520.         case TCP_SYN_SENT:      /* Nothing received or acked yet */
  521.             *sent = *recvd = 0;
  522.             break;
  523.         case TCP_SYN_RECEIVED:
  524.             (*recvd)--;     /* Got SYN, no data acked yet */
  525.             *sent = 0;
  526.             break;
  527.         case TCP_ESTABLISHED:   /* Got and sent SYN */
  528.         case TCP_FINWAIT1:      /* FIN not acked yet */
  529.             (*sent)--;
  530.             (*recvd)--;
  531.             break;
  532.         case TCP_FINWAIT2:      /* Our SYN and FIN both acked */
  533.             *sent -= 2;
  534.             (*recvd)--;
  535.             break;
  536.         case TCP_CLOSE_WAIT:    /* Got SYN and FIN, our FIN not yet acked */
  537.         case TCP_CLOSING:
  538.         case TCP_LAST_ACK:
  539.             (*sent)--;
  540.             *recvd -= 2;
  541.             break;
  542.         case TCP_TIME_WAIT:     /* Sent and received SYN/FIN, all acked */
  543.             *sent -= 2;
  544.             *recvd -= 2;
  545.             break;
  546.     }
  547. }
  548.   
  549. /* TCP View Command - D. Crompton 1/92 */
  550. /* Modified for sorted display and     */
  551. /* two views - tcp view b|t - 3/92     */
  552. int
  553. doview(argc,argv,p)
  554. int argc;
  555. char *argv[];
  556. void *p;
  557.   
  558. {
  559.     register struct tcb *tcb;
  560.     int32 sent,recvd;
  561.     int i,j,k=0,vtype;
  562.     char *buf;
  563.     char temp[80];
  564.   
  565.     if(argc == 1)
  566.         vtype = 1;
  567.     else {
  568.         switch (argv[1][0]) {
  569.             case 'b':  vtype=1;
  570.                 break;
  571.             case 't':  vtype=0;
  572.                 break;
  573.             default:   tputs("Use: tcp view <bytes|timers>\n");
  574.                 return 0;
  575.         }
  576.     }
  577.   
  578.     for(tcb=Tcbs,i=0;tcb != NULLTCB;tcb = tcb->next){
  579.         if(tcb->state == TCP_LISTEN)
  580.             continue;
  581.         i++;
  582.     }
  583.   
  584.     if (i) {
  585.         buf=mallocw(i*80);
  586.   
  587.         if (vtype) {
  588.             tputs("                                               Send  Send       Receive Receive\n" \
  589.             "Remote Socket:Port:Local Port/State   &TCB     Bytes Retries      Bytes Retries\n");
  590.         } else {
  591.             tputs("Remote Socket:Port:Local Port/State   &TCB Boff State      Timer          SRTT\n");
  592.         }
  593.         for(tcb=Tcbs,j=0;tcb != NULLTCB;tcb = tcb->next){
  594.             if(tcb->state == TCP_LISTEN)
  595.                 continue;
  596.   
  597.             strcpy(temp,pinet(&tcb->conn.remote));
  598.             strcat(temp,strstr(pinet(&tcb->conn.local),":"));
  599.             strcat(temp,"/");
  600.             strcat(temp,Tcpstates[tcb->state]);
  601.             temp[37]=0;
  602.             k=sprintf(&buf[j],"%-37s",temp);
  603. #ifdef LINUX
  604.             k += sprintf(&buf[j + k], "%5lx", tcb);
  605. #else
  606.             sprintf(temp,"%8lx",ptol(tcb));
  607.             temp[4]=0;
  608.             k+=sprintf(&buf[j+k]," %4s",temp);
  609. #endif
  610.             if (vtype) {
  611.                 rxtx_data_compute(tcb,&sent,&recvd);
  612.                 k+=sprintf(&buf[j+k],"%10lu ",sent);
  613.                 k+=sprintf(&buf[j+k],"%7lu ",tcb->resent);
  614.                 k+=sprintf(&buf[j+k],"%10lu ",recvd);
  615.                 sprintf(&buf[j+k],"%7lu",tcb->rerecv);
  616.             } else {
  617.                 k+=sprintf(&buf[j+k]," %4u",tcb->backoff);
  618.                 if(tcb->flags.retran)
  619.                     k+=sprintf(&buf[j+k]," Retry ");
  620.                 else
  621.                     k+=sprintf(&buf[j+k],"  Try  ");
  622.                 switch(tcb->timer.state) {
  623.                     case TIMER_STOP:
  624.                         k+=sprintf(&buf[j+k],"      Stopped");
  625.                         break;
  626.                     case TIMER_RUN:
  627.                         k+=sprintf(&buf[j+k]," Run (");
  628.                         if ((long)dur_timer(&tcb->timer)<10000) {
  629.                             k+=sprintf(&buf[j+k],"%ld/%ld)ms",
  630.                             (long)read_timer(&tcb->timer),
  631.                             (long)dur_timer(&tcb->timer));
  632.                         } else {
  633.                             if (((long)read_timer(&tcb->timer)/1000)>9999) {
  634.                                 k+=sprintf(&buf[j+k],">9999/9999)s");
  635.                             } else {
  636.                                 k+=sprintf(&buf[j+k],"%ld/%ld)s",
  637.                                 (long)read_timer(&tcb->timer)/1000,
  638.                                 (long)dur_timer(&tcb->timer)/1000);
  639.                             }
  640.                         }
  641.                         break;
  642.                     case TIMER_EXPIRE:
  643.                         k+=sprintf(&buf[j+k],"      Expired");
  644.                 }
  645.                 for (;k<73;k++)
  646.                     buf[j+k]=' ';
  647.                 if ((tcb->srtt)<10000) {
  648.                     sprintf(&buf[j+73],"%4ldms",tcb->srtt);
  649.                 } else {
  650.                     if ((tcb->srtt/1000)>9999) {
  651.                         sprintf(&buf[j+73],">9999s");
  652.                     } else {
  653.                         sprintf(&buf[j+73],"%4lds",tcb->srtt/1000);
  654.                     }
  655.                 }
  656.             }
  657.             j+=80;
  658.         }
  659.   
  660. #ifdef LINUX
  661.         qsort(buf,(size_t)i,80,(int (*) __ARGS((void*,void*))) strcmp);
  662. #else
  663.         qsort(buf,(size_t)i,80,(int (*) ()) strcmp);
  664. #endif
  665.   
  666.         for (j=0,k=0;j<i;j++,k+=80) {
  667.             tputs(&buf[k]);
  668.             if(tputc('\n') == EOF)
  669.                 return 0;
  670.         }
  671.         free(buf);
  672.     }
  673.     return 0;
  674. }
  675.   
  676. /* tcp timers type - linear v exponential */
  677. static int
  678. tcptimer(argc,argv,p)
  679. int argc ;
  680. char *argv[] ;
  681. void *p ;
  682. {
  683.     if (argc < 2) {
  684.         tprintf("Tcp timer type is %s\n", *(int *)p ? "linear" : "exponential" ) ;
  685.         return 0 ;
  686.     }
  687.   
  688.     switch (argv[1][0]) {
  689.         case 'l':
  690.         case 'L':
  691.             *(int *)p = 1 ;
  692.             break ;
  693.         case 'e':
  694.         case 'E':
  695.             *(int *)p = 0 ;
  696.             break ;
  697.         default:
  698.             tputs("use: tcp timertype [linear|exponential]\n") ;
  699.             return -1 ;
  700.     }
  701.     return 0 ;
  702. }
  703.   
  704. extern int tcptimertype;
  705.   
  706. static int
  707. dotcptimer(argc,argv,p)
  708. int argc ;
  709. char *argv[] ;
  710. void *p ;
  711. {
  712.   
  713.     return tcptimer(argc,argv,(void *)&tcptimertype);
  714. }
  715.   
  716. #ifdef  TCPACCESS
  717. static int
  718. doaccess(argc,argv,p)
  719. int argc;
  720. char *argv[];
  721. void *p;
  722. {
  723.     struct iface *ifp;
  724.     int32 target;
  725.     unsigned bits;
  726.     char *bitp;
  727.     int16 lport,hport,state;
  728.     char *cp; /* for printing the table */
  729.     struct rtaccess *tpacc;
  730.     struct rtaccess *head;
  731.     struct rtaccess *prev;
  732.   
  733.     if(argc == 1){ /* print out the table */
  734.         tputs("IP Address      Mask  Low Port High Port State\n");
  735.         for(tpacc = TCPaccess;tpacc != NULLACCESS;tpacc = tpacc->nxtbits){
  736.             if(tpacc->target != 0)
  737.                 cp = inet_ntoa(tpacc->target);
  738.             else
  739.                 cp = "all";
  740.             tprintf("%-16s",cp);
  741.             tprintf("%4u ",tpacc->bits);
  742.             tprintf("%9u",tpacc->lowport);
  743.             tprintf("%10u ",tpacc->highport);
  744.             if(tpacc->status)
  745.                 cp = "deny";
  746.             else
  747.                 cp = "permit";
  748.             tprintf("%-6s\n",cp);
  749.         }
  750.         return 0;
  751.     }
  752.   
  753.     if(strcmp(argv[1],"permit") == 0){
  754.         state = 0;
  755.     } else {
  756.         if((strcmp(argv[1],"deny") == 0)
  757.         || (strcmp(argv[1],"delete") == 0)){
  758.             state = -1;
  759.         } else {
  760.             tputs(" Format: tcp access <permit|deny|delete> <dest addr>[/<bits>] [lowport [highport]]\n");
  761.             return 1;
  762.         }
  763.     }
  764.     if(strcmp(argv[2],"all") == 0){
  765.         target = 0;
  766.         bits = 0;
  767.     } else {
  768.         /* If IP address is followed by an optional slash and
  769.          * a length field, (e.g., 128.96/16) get it;
  770.          * otherwise assume a full 32-bit address
  771.          */
  772.         if((bitp = strchr(argv[2],'/')) != NULLCHAR){
  773.             /* Terminate address token for resolve() call */
  774.             *bitp++ = '\0';
  775.             bits = atoi(bitp);
  776.         } else
  777.             bits = 32;
  778.   
  779.         if((target = resolve(argv[2])) == 0){
  780.             tprintf(Badhost,argv[2]);
  781.             return 1;
  782.         }
  783.     }
  784.   
  785.     if(argc > 3){
  786.         if(strcmp(argv[3],"all") == 0){
  787.             lport = 1;
  788.             hport = 65534L;
  789.         } else {
  790.             lport = atoi(argv[3]);
  791.             hport = lport;
  792.         }
  793.     } else {
  794.         lport = 0;
  795.         hport = 0;
  796.     }
  797.     if(argc > 4)
  798.         hport = atoi(argv[4]);
  799.   
  800.     if(strcmp(argv[1],"delete") == 0){
  801.         prev = NULLACCESS;
  802.         head = tpacc = TCPaccess;
  803.         while(tpacc != NULLACCESS){
  804.             head = tpacc;
  805.             tpacc = tpacc->nxtbits;
  806.             if((head->target == target) &&
  807.                 (head->bits == bits)     &&
  808.                 (head->lowport == lport) &&
  809.             (head->highport == hport)) { /*match*/
  810.   
  811.   
  812.                 /*now delete. watch for special cases*/
  813.                 if(head == TCPaccess) /* first in chain */
  814.                     TCPaccess = head->nxtbits;
  815.                 else
  816.                     /*
  817.                       sanity check: we cant get here with
  818.                       prev == NULLACCESS !!
  819.                      */
  820.                     prev->nxtbits = tpacc;
  821.                 free(head);
  822.                 return 0;
  823.             }
  824.             prev = head;
  825.         }
  826.         tputs("Not found.\n");
  827.         return 1;
  828.     }
  829.     /* add the access */
  830.     addtaccess(target,bits,lport,hport,state);
  831.     return 0;
  832. }
  833. /* add an entry to the access control list */
  834. /* not a lot of error checking 8-) */
  835. void
  836. addtaccess(target,bits,low,high,permit)
  837. int32 target;           /* Target IP address prefix */
  838. unsigned int bits;      /* Size of target address prefix in bits (0-32) */
  839. int16 low;
  840. int16 high;
  841. int16 permit;
  842. {
  843.     struct rtaccess *tpacc; /*temporary*/
  844.     struct rtaccess *holder; /*for the new record*/
  845.   
  846.     holder = (struct rtaccess *)callocw(1,sizeof(struct rtaccess));
  847.     holder->nxtiface = NULLACCESS;
  848.     holder->nxtbits = NULLACCESS;
  849.     holder->target = target;
  850.     holder->bits = bits;
  851.     holder->lowport = low;
  852.     holder->highport = high;
  853.     holder->status = permit;
  854.     if((tpacc = TCPaccess) == NULLACCESS){
  855.         TCPaccess = holder;
  856.     } else {
  857.         while(tpacc->nxtbits != NULLACCESS)
  858.             tpacc = tpacc->nxtbits;
  859.         tpacc->nxtbits = holder;
  860.     }
  861. }
  862. /* check to see if port is "authorized".  Returns 0 if matching permit record
  863.    is found or no access records exists, -1 if not found or deny record found */
  864. int
  865. tcp_check(accptr,src,port)
  866. struct rtaccess *accptr;
  867. int32 src;
  868. int16 port;
  869. {
  870.     unsigned long mask;
  871.   
  872.     if(accptr == NULLACCESS)
  873.         return 0;               /* no access control */
  874.     for(;accptr != NULLACCESS;accptr = accptr->nxtbits) {
  875.         mask = ~0L << (32 - accptr->bits);
  876.         if(( accptr->target == (mask & src)) &&
  877.             ((( port >= accptr->lowport ) && (port <= accptr->highport))
  878.         || (!accptr->lowport))){
  879.             return (accptr->status);
  880.         }
  881.     }
  882.     return -1; /* fall through to here if not found */
  883. }
  884. #endif
  885.   
  886. /* These are the interface dependent tcp parameters */
  887. static int doiftcpblimit __ARGS((int argc,char *argv[],void *p));
  888. static int doiftcpirtt __ARGS((int argc,char *argv[],void *p));
  889. static int doiftcpmaxwait __ARGS((int argc,char *argv[],void *p));
  890. static int doiftcpretries __ARGS((int argc,char *argv[],void *p));
  891. static int doiftcptimertype __ARGS((int argc,char *argv[],void *p));
  892. static int doiftcpwindow __ARGS((int argc,char *argv[],void *p));
  893. static int doiftcpsyndata __ARGS((int argc,char *argv[],void *p));
  894. static int doiftcpmss __ARGS((int argc,char *argv[],void *p));
  895.   
  896. struct cmds DFAR Iftcpcmds[] = {
  897.     "blimit",   doiftcpblimit,  0, 0, NULLCHAR,
  898.     "irtt",     doiftcpirtt,    0, 0, NULLCHAR,
  899.     "maxwait",  doiftcpmaxwait, 0, 0, NULLCHAR,
  900.     "mss",      doiftcpmss,     0, 0, NULLCHAR,
  901.     "retries",  doiftcpretries, 0, 0, NULLCHAR,
  902.     "syndata",  doiftcpsyndata, 0, 0, NULLCHAR,
  903.     "timertype",doiftcptimertype,0,0, NULLCHAR,
  904.     "window",   doiftcpwindow,  0, 0, NULLCHAR,
  905.     NULLCHAR
  906. };
  907.   
  908. int doiftcp(int argc, char *argv[],void *p) {
  909.     if(!p)
  910.         return 0;
  911.     return subcmd(Iftcpcmds,argc,argv,p);
  912. }
  913.   
  914. int doiftcpblimit(int argc,char *argv[],void *p) {
  915.     struct iface *ifp = p;
  916.   
  917.     return tcpblimit(argc,argv,(void *)&ifp->tcp->blimit);
  918. }
  919.   
  920. int doiftcpirtt(int argc,char *argv[],void *p) {
  921.     struct iface *ifp = p;
  922.   
  923.     return tcpirtt(argc,argv,(void *)&ifp->tcp->irtt);
  924. }
  925.   
  926. int doiftcpmaxwait(int argc,char *argv[],void *p) {
  927.     struct iface *ifp = p;
  928.   
  929.     return tcpmaxwait(argc,argv,(void *)&ifp->tcp->maxwait);
  930. }
  931.   
  932. int doiftcpmss(int argc,char *argv[],void *p) {
  933.     struct iface *ifp = p;
  934.   
  935.     return tcpmss(argc,argv,(void *)&ifp->tcp->mss);
  936. }
  937.   
  938. int doiftcpretries(int argc,char *argv[],void *p) {
  939.     struct iface *ifp = p;
  940.   
  941.     return tcpretries(argc,argv,(void *)&ifp->tcp->retries);
  942. }
  943.   
  944. int doiftcptimertype(int argc,char *argv[],void *p) {
  945.     struct iface *ifp = p;
  946.   
  947.     return tcptimer(argc,argv,(void *)&ifp->tcp->timertype);
  948. }
  949.   
  950. int doiftcpwindow(int argc,char *argv[],void *p) {
  951.     struct iface *ifp = p;
  952.   
  953.     return tcpwindow(argc,argv,(void *)&ifp->tcp->window);
  954. }
  955.   
  956. int doiftcpsyndata(int argc,char *argv[],void *p) {
  957.     struct iface *ifp = p;
  958.   
  959.     return tcpsyndata(argc,argv,(void *)&ifp->tcp->syndata);
  960. }
  961.   
  962. void init_iftcp(struct iftcp *tcp) {
  963.     tcp->blimit = Tcp_blimit;
  964.     tcp->maxwait = Tcp_maxwait;
  965.     tcp->window = Tcp_window;
  966.     tcp->mss = Tcp_mss;
  967.     tcp->irtt = Tcp_irtt;
  968.     tcp->retries = Tcp_retries;
  969.     tcp->timertype = tcptimertype;
  970.     tcp->syndata = Tcp_syndata;
  971. }
  972.   
  973.