home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 3 / hamradioversion3.0examsandprograms1992.iso / packet / n17jsrc / rspfcmd.c < prev    next >
C/C++ Source or Header  |  1991-06-07  |  10KB  |  399 lines

  1. #include "global.h"
  2. #include "mbuf.h"
  3. #include "timer.h"
  4. #include "iface.h"
  5. #include "cmdparse.h"
  6. #include "netuser.h"
  7. #include "socket.h"
  8. #include "rspf.h"
  9.  
  10. int Rspfownmode = -1;
  11. static int dointerface __ARGS((int argc,char *argv[],void *p));
  12. static int domessage __ARGS((int argc,char *argv[],void *p));
  13. static int domaxping __ARGS((int argc,char *argv[],void *p));
  14. static int domode __ARGS((int argc,char *argv[],void *p));
  15. static int dorrhtimer __ARGS((int argc,char *argv[],void *p));
  16. static int dotimer __ARGS((int argc,char *argv[],void *p));
  17. static int doroutes __ARGS((int argc,char *argv[],void *p));
  18. static int dostatus __ARGS((int argc,char *argv[],void *p));
  19. static int dosuspect __ARGS((int argc,char *argv[],void *p));
  20. static struct timer rrhtimer, rspftimer;
  21.  
  22. static struct cmds Rspfcmds[] = {
  23.     "interface",    dointerface,    0,    0,    NULLCHAR,
  24.     "message",    domessage,    0,    0,    NULLCHAR,
  25.     "maxping",    domaxping,    0,    0,    NULLCHAR,
  26.     "mode",        domode,        0,    0,    NULLCHAR,
  27.     "rrhtimer",    dorrhtimer,    0,    0,    NULLCHAR,
  28.     "routes",    doroutes,    0,    0,    NULLCHAR,
  29.     "status",    dostatus,    0,    0,    NULLCHAR,
  30.     "suspecttimer",    dosuspect,    0,    0,    NULLCHAR,
  31.     "timer",    dotimer,    0,    0,    NULLCHAR,
  32.     NULLCHAR
  33. };
  34.  
  35. int
  36. dorspf(argc,argv,p)
  37. int argc;
  38. char *argv[];
  39. void *p;
  40. {
  41.     return subcmd(Rspfcmds,argc,argv,p);
  42. }
  43.  
  44. /* The suspect timer controls how often old links expire. When a link has
  45.  * expired, we try to renew its entry by various methods.
  46.  */
  47. static int
  48. dosuspect(argc,argv,p)
  49. int argc;
  50. char *argv[];
  51. void *p;
  52. {
  53.     if(Rspfifaces == NULLRIFACE){
  54.         tprintf("RSPF is not active - define interface first.\n");
  55.         return 0;
  56.     }
  57.     if(argc < 2){
  58.         tprintf("Suspect timer: %lu/%lu seconds\n",
  59.             read_timer(&Susptimer)/1000,
  60.             dur_timer(&Susptimer)/1000);
  61.         return 0;
  62.     }
  63.     Susptimer.func = rspfsuspect; /* what to call on timeout */
  64.     Susptimer.arg = NULL;            /* dummy value */
  65.     set_timer(&Susptimer,atol(argv[1])*1000L); /* set timer duration */
  66.     start_timer(&Susptimer);        /* and fire it up */
  67.     return 0;
  68. }
  69.  
  70. /* The RRH timer controls the interval between Router-To-Router Hello
  71.  * messages. These messages announce that your station is live and well
  72.  * and that you are willing to exchange RSPF routing updates.
  73.  */
  74. static int
  75. dorrhtimer(argc,argv,p)
  76. int argc;
  77. char *argv[];
  78. void *p;
  79. {
  80.     if(Rspfifaces == NULLRIFACE){
  81.         tprintf("RSPF is not active - define interface first.\n");
  82.         return 0;
  83.     }
  84.     if(argc < 2){
  85.         tprintf("RRH timer: %lu/%lu seconds\n",
  86.             read_timer(&rrhtimer)/1000,
  87.             dur_timer(&rrhtimer)/1000);
  88.         return 0;
  89.     }
  90.     rrhtimer.func = rspfevent; /* what to call on timeout */
  91.     rrhtimer.arg = (void *) &rrhtimer;
  92.     set_timer(&rrhtimer,atol(argv[1])*1000L); /* set timer duration */
  93.     start_timer(&rrhtimer);        /* and fire it up */
  94.     return 0;
  95. }
  96.  
  97. /* This timer controls the interval between the RSPF routing updates. */
  98. static int
  99. dotimer(argc,argv,p)
  100. int argc;
  101. char *argv[];
  102. void *p;
  103. {
  104.     if(Rspfifaces == NULLRIFACE){
  105.         tprintf("RSPF is not active - define interface first.\n");
  106.         return 0;
  107.     }
  108.     if(argc < 2){
  109.         tprintf("RSPF update timer: %lu/%lu seconds\n",
  110.             read_timer(&rspftimer)/1000,
  111.             dur_timer(&rspftimer)/1000);
  112.         return 0;
  113.     }
  114.     rspftimer.func = rspfevent; /* what to call on timeout */
  115.     rspftimer.arg = (void *) &rspftimer;
  116.     set_timer(&rspftimer,atol(argv[1])*1000L); /* set timer duration */
  117.     start_timer(&rspftimer);        /* and fire it up */
  118.     return 0;
  119. }
  120.  
  121. /* Called when either the RRH timer, the Update timer or the Suspect timer
  122.  * expires.
  123.  */
  124. void
  125. rspfevent(t)
  126. void *t;
  127. {
  128.      int cmd;
  129.      struct mbuf *bp;
  130.      struct rspfadj *adj = NULLADJ;
  131.      struct timer *tp;
  132.      tp = (struct timer *) t;
  133.      if(tp == &rrhtimer) {
  134.       cmd = RSPFE_RRH;
  135.       start_timer(tp);
  136.      }
  137.      else if(tp == &rspftimer) {
  138.       cmd = RSPFE_UPDATE;
  139.       start_timer(tp);
  140.      }
  141.      else {
  142.       for(adj = Adjs; adj != NULLADJ; adj = adj->next)
  143.            if(&adj->timer == tp)
  144.             break;
  145.       if(adj == NULLADJ)
  146.            return;
  147.       cmd = RSPFE_CHECK;
  148.      }
  149.      bp = ambufw(1+sizeof(int32));
  150.      *bp->data = cmd;
  151.      memcpy(bp->data + 1,&adj,sizeof(adj));
  152.      bp->cnt = bp->size;
  153.      enqueue(&Rspfinq,bp);
  154. }
  155.  
  156. static int
  157. domessage(argc,argv,p)
  158. int argc;
  159. char *argv[];
  160. void *p;
  161. {
  162.     if(argc > 2) {
  163.         tputs("Usage: rspf message \"<your message>\"\n");
  164.         return 0;
  165.     }
  166.  
  167.     if(argc < 2) {
  168.         if(Rrh_message != NULLCHAR)
  169.             tputs(Rrh_message);
  170.     }
  171.     else {
  172.         if(Rrh_message != NULLCHAR){
  173.             free(Rrh_message);
  174.             Rrh_message = NULLCHAR;    /* reset the pointer */
  175.         }
  176.         if(!strlen(argv[1]))
  177.             return 0;        /* clearing the buffer */
  178.         Rrh_message = mallocw(strlen(argv[1])+5);/* allow for EOL */
  179.         strcpy(Rrh_message, argv[1]);
  180.         strcat(Rrh_message, INET_EOL);    /* add the EOL char */
  181.     }
  182.     return 0;
  183. }
  184.  
  185. static int
  186. domaxping(argc,argv,p)
  187. int argc;
  188. char *argv[];
  189. void *p;
  190. {
  191.      return setshort(&Rspfpingmax,"Max failed pings before deleting adjacency",
  192.              argc,argv);
  193. }
  194.  
  195. static int
  196. domode(argc,argv,p)
  197. int argc;
  198. char *argv[];
  199. void *p;
  200. {
  201.     if(argc < 2) {
  202.     tputs("RSPF preferred mode is ");
  203.     if(Rspfownmode == -1)
  204.         tputs("not set.\n");
  205.     else
  206.         tprintf("%s.\n",(Rspfownmode & CONNECT_MODE) ? "VC mode" :
  207.            "Datagram mode");
  208.     return 0;
  209.     }
  210.     switch(*argv[1]){
  211.     case 'v':
  212.     case 'c':
  213.     case 'V':
  214.     case 'C':
  215.     Rspfownmode = CONNECT_MODE;
  216.     break;
  217.     case 'd':
  218.     case 'D':
  219.     Rspfownmode = DATAGRAM_MODE;
  220.     break;
  221.     case 'n':
  222.     case 'N':
  223.     Rspfownmode = -1;
  224.     break;
  225.     default:
  226.     tputs("Usage: rspf mode [vc | datagram | none]\n");
  227.     return 1;
  228.     }
  229.     return 0;
  230. }
  231.  
  232. static int
  233. dointerface(argc,argv,p)
  234. int argc;
  235. char *argv[];
  236. void *p;
  237. {
  238.     struct rspfiface *riface;
  239.     struct iface *iface;
  240.     struct mbuf *bp;
  241.     int h,q;
  242.     if(argc < 2){
  243.     tputs("Iface    Quality    Horizon\n");
  244.     for(riface = Rspfifaces; riface != NULLRIFACE; riface = riface->next)
  245.         tprintf("%-9s%-11d%-11d\n",riface->iface->name,riface->quality,
  246.            riface->horizon);
  247.     return 0;
  248.     }
  249.     if(argc != 4){
  250.     tputs("Usage: rspf interface <name> <quality> <horizon>\n");
  251.     return 1;
  252.     }
  253.     if((iface = if_lookup(argv[1])) == NULLIF){
  254.     tputs("No such interface.\n");
  255.     return 1;
  256.     }
  257.     if(iface->broadcast == 0){
  258.     tprintf("Broadcast address for interface %s not set\n",argv[1]);
  259.     return 1;
  260.     }
  261.     q = atoi(argv[2]);
  262.     if(q < 1 || q > 127){
  263.     tputs("Quality must be between 1 and 127\n");
  264.     return 1;
  265.     }
  266.     h = atoi(argv[3]);
  267.     if(h < 1 || h > 255){
  268.     tputs("Horizon must be between 1 and 255\n");
  269.     return 1;
  270.     }
  271.     riface = (struct rspfiface *)callocw(1,sizeof(struct rspfiface));
  272.     riface->iface = iface;
  273.     riface->quality = q;
  274.     riface->horizon = h;
  275.     riface->next = Rspfifaces;
  276.     if(Rspfifaces == NULLRIFACE)
  277.      newproc("RSPF",2048,rspfmain,0,NULL,NULL,0);
  278.     Rspfifaces = riface;
  279.     bp = ambufw(1+sizeof(int32));
  280.     *bp->data = RSPFE_RRH;        /* Send an RRH immediately */
  281.     memcpy(bp->data + 1,&riface,sizeof(riface));
  282.     bp->cnt = bp->size;
  283.     enqueue(&Rspfinq,bp);
  284.     return 0;
  285. }
  286.  
  287. /* Display accumulated routing updates */
  288. static int
  289. doroutes(argc,argv,p)
  290. int argc;
  291. char *argv[];
  292. void *p;
  293. {
  294.     struct mbuf *bp;
  295.     struct rspfrouter *rr;
  296.     if(Rspfifaces == NULLRIFACE){
  297.     tprintf("RSPF is not active - define interface first.\n");
  298.     return 0;
  299.     }
  300.     bp = makeownupdate(INADDR_ANY,0);
  301.     if(bp == NULLBUF && Rspfrouters == NULLRROUTER) {
  302.      tputs("No routing information is available.\n");
  303.      return 0;
  304.     }
  305.     if(bp != NULLBUF) {
  306.     tputs("      Local routing update:\n");
  307.     rspfnodedump(NULLFILE,&bp,0);
  308.     tputc('\n');
  309.     }
  310.     for(rr = Rspfrouters; rr != NULLRROUTER; rr = rr->next) {
  311.     tprintf("      Time since receipt: %s",tformat(secclock() - rr->time));
  312.     if(rr->subseq != 0)
  313.          tprintf("  Last subseq: %u",uchar(rr->subseq));
  314.     if(rr->sent)
  315.          tputs("  Propagated");
  316.     tputc('\n');
  317.     if(rr->data != NULLBUF) {
  318.          dup_p(&bp,rr->data,0,len_p(rr->data));
  319.          rspfnodedump(NULLFILE,&bp,0);
  320.          tputc('\n');
  321.     }
  322.     }
  323.     return 0;
  324. }
  325.  
  326. static int
  327. dostatus(argc,argv,p)
  328. int argc;
  329. char *argv[];
  330. void *p;
  331. {
  332.     struct rspfreasm *re;
  333.     struct rspfadj *adj;
  334.     struct mbuf *bp;
  335.     union rspf rspf;
  336.     if(Rspfifaces == NULLRIFACE){
  337.         tprintf("RSPF is not active - define interface first.\n");
  338.         return 0;
  339.     }
  340.     tprintf("Bad checksum %u  Bad version %u  Not RSPF interface %u\n",
  341.         Rspf_stat.badcsum,Rspf_stat.badvers,Rspf_stat.norspfiface);
  342.     tprintf("RRH in %u  RRH out %u  Update in %u  Update out %u\n",
  343.         Rspf_stat.rrhin,Rspf_stat.rrhout,Rspf_stat.updatein,
  344.         Rspf_stat.updateout);
  345.     tprintf("Non-adjacency update %u  Old node report %u  Polls sent %u\n",
  346.         Rspf_stat.noadjupdate,Rspf_stat.oldreport,Rspf_stat.outpolls);
  347.     if(Adjs == NULLADJ)
  348.         return 0;
  349.     tputs("Addr            Cost    Seq    Heard    Timer     TOS    State\n");
  350.     for(adj = Adjs; adj != NULLADJ; adj = adj->next) {
  351.         tprintf("%-15s %4u  %5u   %6lu ", inet_ntoa(adj->addr),
  352.             uchar(adj->cost),adj->seq,adj->heard);
  353.         if(run_timer(&adj->timer))
  354.              tprintf("%5lu/%-5lu",
  355.             read_timer(&adj->timer)/1000L ,dur_timer(&adj->timer)/1000L);
  356.         else
  357.              tprintf("%11s","");
  358.         tprintf("  %3u    ", uchar(adj->tos));
  359.         switch(adj->state) {
  360.         case RSPF_TENTATIVE:
  361.             tputs("Tentative");
  362.             break;
  363.         case RSPF_OK:
  364.             tputs("OK");
  365.             break;
  366.         case RSPF_SUSPECT:
  367.             tputs("Suspect");
  368.             break;
  369.         case RSPF_BAD:
  370.             tputs("Bad");
  371.             break;
  372.         default:
  373.             tputs("Unknown");
  374.             break;
  375.         }
  376.         tputc('\n');
  377.     }
  378.     if(run_timer(&Rspfreasmt)) {
  379.          tprintf("Reassembly timer running: %lu/%lu seconds\n",
  380.              read_timer(&Rspfreasmt)/1000L, dur_timer(&Rspfreasmt)/1000L);
  381.     }
  382.     if(Rspfreasmq != NULLRREASM)
  383.          tputs("Reassembly fragments:\n");
  384.     for(re = Rspfreasmq; re != NULLRREASM; re = re->next) {
  385.          tprintf("src %s time since last frag %s",inet_ntoa(re->addr),
  386.              tformat((secclock() - re->time)));
  387.          if(dup_p(&bp,re->data,0,RSPFPKTLEN) == RSPFPKTLEN &&
  388.         ntohrspf(&rspf,&bp) != -1)
  389.           tprintf(" frag count %u/%u\n",len_q(re->data),
  390.               rspf.pkthdr.fragtot);
  391.          else {
  392.           tputc('\n');
  393.           free_p(bp);
  394.           continue;
  395.          }
  396.     }
  397.     return 0;
  398. }
  399.