home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / network / src_1218.zip / NRCMD.C < prev    next >
C/C++ Source or Header  |  1991-03-10  |  23KB  |  960 lines

  1. /* net/rom user command processing
  2.  * Copyright 1989 by Daniel M. Frank, W9NK.  Permission granted for
  3.  * non-commercial distribution only.
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <ctype.h>
  8. #include "global.h"
  9. #include "mbuf.h"
  10. #include "ax25.h"
  11. #include "mailbox.h"
  12. #include "netrom.h"
  13. #include "nr4.h"
  14. #include "timer.h"
  15. #include "iface.h"
  16. #include "lapb.h"
  17. #include "cmdparse.h"
  18. #include "session.h"
  19. #include "socket.h"
  20. #include "commands.h"
  21.  
  22. char Nr4user[AXALEN];
  23.  
  24. char *Nr4states[] = {
  25.     "Disconnected",
  26.     "Conn Pending",
  27.     "Connected",
  28.     "Disc Pending",
  29.     "Listening"
  30. } ;
  31.  
  32. char *Nr4reasons[] = {
  33.     "Normal",
  34.     "By Peer",
  35.     "Timeout",
  36.     "Reset",
  37.     "Refused"
  38. } ;
  39. static int dobcnodes __ARGS((int argc,char *argv[],void *p));
  40. static int dointerface __ARGS((int argc,char *argv[],void *p));
  41. static int donfadd __ARGS((int argc,char *argv[],void *p));
  42. static int donfdrop __ARGS((int argc,char *argv[],void *p));
  43. static int donfdump __ARGS((void));
  44. static int donfmode __ARGS((int argc,char *argv[],void *p));
  45. static int donodefilter __ARGS((int argc,char *argv[],void *p));
  46. static void donodetick __ARGS((void));
  47. static int donodetimer __ARGS((int argc,char *argv[],void *p));
  48. static int donracktime __ARGS((int argc,char *argv[],void *p));
  49. static int donrchoketime __ARGS((int argc,char *argv[],void *p));
  50. static int donrconnect __ARGS((int argc,char *argv[],void *p));
  51. static int donrirtt __ARGS((int argc,char *argv[],void *p));
  52. static int donrkick __ARGS((int argc,char *argv[],void *p));
  53. static int dorouteadd __ARGS((int argc,char *argv[],void *p));
  54. static int doroutedrop __ARGS((int argc,char *argv[],void *p));
  55. static int donrqlimit __ARGS((int argc,char *argv[],void *p));
  56. static int donrreset __ARGS((int argc,char *argv[],void *p));
  57. static int donrretries __ARGS((int argc,char *argv[],void *p));
  58. static int donrroute __ARGS((int argc,char *argv[],void *p));
  59. static int donrstatus __ARGS((int argc,char *argv[],void *p));
  60. static int donrttl __ARGS((int argc,char *argv[],void *p));
  61. static int donruser __ARGS((int argc,char *argv[],void *p));
  62. static int donrverbose __ARGS((int argc,char *argv[],void *p));
  63. static int donrwindow __ARGS((int argc,char *argv[],void *p));
  64. static void doobsotick __ARGS((void));
  65. static int doobsotimer __ARGS((int argc,char *argv[],void *p));
  66.  
  67. static struct cmds Nrcmds[] = {
  68.     "acktime",    donracktime,    0, 0,    NULLCHAR,
  69.     "bcnodes",    dobcnodes,    0, 2,    "netrom bcnodes <interface>",
  70.     "connect",    donrconnect, 1024, 2,    "netrom connect <node>",
  71.     "choketime",    donrchoketime,    0, 0,    NULLCHAR,
  72.     "interface",    dointerface,    0, 4,
  73.         "netrom interface <interface> <alias> <quality>",
  74.     "irtt",        donrirtt,    0, 0,    NULLCHAR,
  75.     "kick",        donrkick,    0, 2,    "netrom kick <&nrcb>",
  76.     "nodefilter",    donodefilter,    0, 0,    NULLCHAR,
  77.     "nodetimer",    donodetimer,    0, 0,    NULLCHAR,
  78.     "obsotimer",    doobsotimer,    0, 0,    NULLCHAR,
  79.     "qlimit",    donrqlimit,    0, 0,    NULLCHAR,
  80.     "reset",    donrreset,    0, 2,    "netrom reset <&nrcb>",
  81.     "retries",    donrretries,    0, 0,    NULLCHAR,
  82.     "route",    donrroute,    0, 0,    NULLCHAR,
  83.     "status",    donrstatus,    0, 0,    NULLCHAR,
  84.     "ttl",        donrttl,    0, 0,    NULLCHAR,
  85.     "user",        donruser,    0, 0,    NULLCHAR,
  86.     "verbose",    donrverbose,    0, 0,    NULLCHAR,
  87.     "window",    donrwindow,    0, 0,    NULLCHAR,
  88.     NULLCHAR,
  89. } ;
  90.  
  91. static struct timer Nodetimer ;    /* timer for nodes broadcasts */
  92. static struct timer Obsotimer ;    /* timer for aging routes */
  93.  
  94. /* Command multiplexer */
  95. int
  96. donetrom(argc,argv,p)
  97. int argc ;
  98. char *argv[] ;
  99. void *p;
  100. {
  101.     return subcmd(Nrcmds,argc,argv,p) ;
  102. }
  103.  
  104. static struct cmds Routecmds[] = {
  105.     "add",    dorouteadd,    0, 6,
  106.         "netrom route add <alias> <destination> <interface> <quality> <neighbor>",
  107.     "drop",    doroutedrop, 0, 4,
  108.         "netrom route drop <destination> <neighbor> <interface>",
  109.     "info", dorouteinfo, 0, 2,
  110.         "netrom route info <destination>",
  111.     NULLCHAR,
  112. } ;
  113.  
  114. /* Route command multiplexer */
  115. static int
  116. donrroute(argc, argv,p)
  117. int argc ;
  118. char *argv[] ;
  119. void *p;
  120. {
  121.     if (argc < 2) {
  122.         doroutedump() ;
  123.         return 0 ;
  124.     }
  125.     return subcmd(Routecmds,argc,argv,p) ;
  126. }
  127.  
  128. /* Dump a list of known routes */
  129. int
  130. doroutedump()
  131. {
  132.     register struct nrroute_tab *rp ;
  133.     register int i, column ;
  134.     char buf[16] ;
  135.     char *cp ;
  136.     
  137.     column = 1 ;
  138.     
  139.     for (i = 0 ; i < NRNUMCHAINS ; i++)
  140.         for (rp = Nrroute_tab[i] ; rp != NULLNRRTAB ; rp = rp->next) {
  141.             strcpy(buf,rp->alias) ;
  142.             /* remove trailing spaces */
  143.             if ((cp = strchr(buf,' ')) == NULLCHAR)
  144.                 cp = &buf[strlen(buf)] ;
  145.             if (cp != buf)        /* don't include colon for null alias */
  146.                 *cp++ = ':' ;
  147.             pax25(cp,rp->call) ;
  148.             tprintf("%-16s  ",buf) ;
  149.             if (column++ == 4) {
  150.                 if(tprintf("\n") == EOF)
  151.                     return 0;
  152.                 column = 1 ;
  153.             }
  154.         }
  155.  
  156.     if (column != 1)
  157.         tprintf("\n") ;
  158.         
  159.     return 0 ;
  160. }
  161.  
  162. /* print detailed information on an individual route */
  163. int
  164. dorouteinfo(argc,argv,p)
  165. int argc ;
  166. char *argv[] ;
  167. void *p;
  168. {
  169.     register struct nrroute_tab *rp ;
  170.     register struct nr_bind *bp ;
  171.     register struct nrnbr_tab *np ;
  172.     char dest[AXALEN] ;
  173.     char neighbor[AXBUF] ;
  174.  
  175.     if (setcall(dest,argv[1]) == -1) {
  176.         tprintf ("bad destination name\n") ;
  177.         return -1 ;
  178.     }
  179.         
  180.     if ((rp = find_nrroute(dest)) == NULLNRRTAB) {
  181.         tprintf("no such route\n") ;
  182.         return -1 ;
  183.     }
  184.  
  185.     for (bp = rp->routes ; bp != NULLNRBIND ; bp = bp->next) {
  186.         np = bp->via ;
  187.         if(tprintf("%1s %3d  %3d  %-8s  %s\n",
  188.          (bp->flags & NRB_PERMANENT ? "P" :
  189.          bp->flags & NRB_RECORDED ? "R" : " "),
  190.          bp->quality,bp->obsocnt,
  191.          Nrifaces[np->iface].iface->name,
  192.          pax25(neighbor,np->call)) == EOF)
  193.             break;
  194.     }
  195.     return 0 ;
  196. }
  197.         
  198. /* convert a null-terminated alias name to a blank-filled, upcased */
  199. /* version.  Return -1 on failure. */
  200. int
  201. putalias(to,from,complain)
  202. register char *to, *from ;
  203. int complain ;    
  204. {
  205.     int len, i ;
  206.     
  207.     if ((len = strlen(from)) > ALEN) {
  208.         if (complain)
  209.             tprintf ("alias too long - six characters max\n") ;
  210.         return -1 ;
  211.     }
  212.     
  213.     for (i = 0 ; i < ALEN ; i++) {
  214.         if (i < len) {
  215.             if (islower(*from))
  216.                 *to++ = toupper(*from++) ;
  217.             else
  218.                 *to++ = *from++ ;
  219.         }
  220.         else
  221.             *to++ = ' ' ;
  222.     }
  223.             
  224.     *to = '\0' ;
  225.     return 0 ;
  226. }
  227.  
  228. /* Add a route */
  229. static int
  230. dorouteadd(argc, argv,p)
  231. int argc ;
  232. char *argv[] ;
  233. void *p;
  234. {
  235.     char alias[AXALEN] ;
  236.     char dest[AXALEN] ;
  237.     unsigned quality ;
  238.     char neighbor[AXALEN] ;
  239.     register int i ;
  240.     int naddr ;
  241.  
  242.     /* format alias (putalias prints error message if necessary) */
  243.     if (putalias(alias,argv[1],1) == -1)
  244.         return -1 ;
  245.  
  246.     /* format destination callsign */
  247.     if (setcall(dest,argv[2]) == -1) {
  248.         tprintf("bad destination callsign\n") ;
  249.         return -1 ;
  250.     }
  251.  
  252.     /* find interface */
  253.     for (i = 0 ; i < Nr_numiface ; i++)
  254.         if (!strcmp(Nrifaces[i].iface->name,argv[3]))
  255.             break ;
  256.     if (i == Nr_numiface) {
  257.         tprintf("Interface \"%s\" not found\n",argv[3]) ;
  258.         return -1 ;
  259.     }
  260.     
  261.     /* get and check quality value */
  262.     if ((quality = atoi(argv[4])) > 255) {
  263.         tprintf("maximum route quality is 255\n") ;
  264.         return -1 ;
  265.     }
  266.  
  267.     /* Change from 871225 -- no digis in net/rom table */
  268.     naddr = argc - 5 ;
  269.     if (naddr > 1) {
  270.         tprintf("Use the ax25 route command to specify digipeaters\n") ;
  271.         return -1 ;
  272.     }
  273.     
  274.     /* format neighbor address string */
  275.     setcall(neighbor,argv[5]) ;
  276.  
  277.     return nr_routeadd(alias,dest,i,quality,neighbor,1,0) ;
  278. }
  279.  
  280.  
  281. /* drop a route */
  282. static int
  283. doroutedrop(argc,argv,p)
  284. int argc ;
  285. char *argv[] ;
  286. void *p;
  287. {
  288.     char dest[AXALEN], neighbor[AXALEN] ;
  289.     register int i ;
  290.  
  291.     /* format destination and neighbor callsigns */
  292.     if (setcall(dest,argv[1]) == -1) {
  293.         tprintf("bad destination callsign\n") ;
  294.         return -1 ;
  295.     }
  296.     if (setcall(neighbor,argv[2]) == -1) {
  297.         tprintf("bad neighbor callsign\n") ;
  298.         return -1 ;
  299.     }
  300.  
  301.     /* find interface */
  302.     for (i = 0 ; i < Nr_numiface ; i++)
  303.         if (!strcmp(Nrifaces[i].iface->name,argv[3]))
  304.             break ;
  305.     if (i == Nr_numiface) {
  306.         tprintf("Interface \"%s\" not found\n",argv[3]) ;
  307.         return -1 ;
  308.     }
  309.  
  310.     return nr_routedrop(dest,neighbor,i) ;
  311. }
  312.     
  313.     
  314. /* make an interface available to net/rom */
  315. static int
  316. dointerface(argc,argv,p)
  317. int argc ;
  318. char *argv[] ;
  319. void *p;
  320. {
  321.     int i ;
  322.     register struct iface *ifp ;
  323.  
  324.     if (Nr_iface == NULLIF) {
  325.         tprintf("Attach netrom interface first\n") ;
  326.         return 1 ;
  327.     }
  328.     
  329.     if (Nr_numiface >= NRNUMIFACE) {
  330.         tprintf("Only %d net/rom interfaces available\n",NRNUMIFACE) ;
  331.         return 1 ;
  332.     }
  333.     
  334.     if((ifp = if_lookup(argv[1])) == NULLIF){
  335.         tprintf("Interface \"%s\" unknown\n",argv[1]);
  336.         return 1;
  337.     }
  338.     for (i = 0 ; i < Nr_numiface ; i++)
  339.         if (Nrifaces[i].iface == ifp) {
  340.             tprintf("Interface \"%s\" is already registered\n",argv[1]) ;
  341.             return 1 ;
  342.         }
  343.         
  344.     Nrifaces[Nr_numiface].iface = ifp ;
  345.  
  346.     if (putalias(Nrifaces[Nr_numiface].alias,argv[2],1) == -1)
  347.         return 1 ;
  348.         
  349.     if ((Nrifaces[Nr_numiface].quality = atoi(argv[3])) > 255) {
  350.         tprintf("Quality cannot be greater than 255\n") ;
  351.         return 1 ;
  352.     }
  353.         
  354.     Nr_numiface++ ;            /* accept this interface */
  355.     return 0 ;
  356. }
  357.  
  358. /* Broadcast nodes list on named interface. */
  359. static int
  360. dobcnodes(argc,argv,p)
  361. int argc ;
  362. char *argv[] ;
  363. void *p;
  364. {
  365.     register int i ;
  366.  
  367.     for (i = 0 ; i < Nr_numiface ; i++)
  368.         if (!strcmp(Nrifaces[i].iface->name,argv[1]))
  369.             break ;
  370.     if (i == Nr_numiface) {
  371.         tprintf("Interface \"%s\" not found\n",argv[1]) ;
  372.         return 1 ;
  373.     }
  374.         
  375.     nr_bcnodes(i) ;
  376.     return 0;
  377. }
  378.  
  379. /* Set outbound node broadcast interval */
  380. static int
  381. donodetimer(argc,argv,p)
  382. int argc;
  383. char *argv[];
  384. void *p;
  385. {
  386.     if(argc < 2){
  387.         tprintf("Nodetimer %lu/%lu seconds\n",
  388.             read_timer(&Nodetimer)/1000L,
  389.             dur_timer(&Nodetimer)/1000L);
  390.         return 0;
  391.     }
  392.     stop_timer(&Nodetimer) ;    /* in case it's already running */
  393.     Nodetimer.func = (void (*)())donodetick;/* what to call on timeout */
  394.     Nodetimer.arg = NULLCHAR;        /* dummy value */
  395.     set_timer(&Nodetimer,atoi(argv[1])*1000L);/* set timer duration */
  396.     start_timer(&Nodetimer);        /* and fire it up */
  397.     return 0;
  398. }
  399.  
  400. static void
  401. donodetick()
  402. {
  403.     register int i ;
  404.  
  405.     for (i = 0 ; i < Nr_numiface ; i++)
  406.         nr_bcnodes(i) ;
  407.  
  408.     /* Restart timer */
  409.     start_timer(&Nodetimer) ;
  410. }
  411.  
  412. /* Set timer for aging routes */
  413. static int
  414. doobsotimer(argc,argv,p)
  415. int argc;
  416. char *argv[];
  417. void *p;
  418. {
  419.     if(argc < 2){
  420.         tprintf("Obsotimer %lu/%lu seconds\n",
  421.             read_timer(&Obsotimer)/1000L,
  422.             dur_timer(&Obsotimer)/1000L);
  423.         return 0;
  424.     }
  425.     stop_timer(&Obsotimer) ;    /* just in case it's already running */
  426.     Obsotimer.func = (void (*)())doobsotick;/* what to call on timeout */
  427.     Obsotimer.arg = NULLCHAR;        /* dummy value */
  428.     set_timer(&Obsotimer,atoi(argv[1])*1000L);    /* set timer duration */
  429.     start_timer(&Obsotimer);        /* and fire it up */
  430.     return 0;
  431. }
  432.  
  433.  
  434. /* Go through the routing table, reducing the obsolescence count of
  435.  * non-permanent routes, and purging them if the count reaches 0
  436.  */
  437. static void
  438. doobsotick()
  439. {
  440.     register struct nrnbr_tab *np ;
  441.     register struct nrroute_tab *rp, *rpnext ;
  442.     register struct nr_bind *bp, *bpnext ;
  443.     int i ;
  444.  
  445.     for (i = 0 ; i < NRNUMCHAINS ; i++) {
  446.         for (rp = Nrroute_tab[i] ; rp != NULLNRRTAB ; rp = rpnext) {
  447.             rpnext = rp->next ;     /* save in case we free this route */
  448.             for (bp = rp->routes ; bp != NULLNRBIND ; bp = bpnext) {
  449.                 bpnext = bp->next ;    /* in case we free this binding */
  450.                 if (bp->flags & NRB_PERMANENT)    /* don't age these */
  451.                     continue ;
  452.                 if (--bp->obsocnt == 0) {        /* time's up! */
  453.                     if (bp->next != NULLNRBIND)
  454.                         bp->next->prev = bp->prev ;
  455.                     if (bp->prev != NULLNRBIND)
  456.                         bp->prev->next = bp->next ;
  457.                     else
  458.                         rp->routes = bp->next ;
  459.                     rp->num_routes-- ;            /* one less binding */
  460.                     np = bp->via ;                /* find the neighbor */
  461.                     free((char *)bp) ;                /* now we can free the bind */
  462.                     /* Check to see if we can free the neighbor */
  463.                     if (--np->refcnt == 0) {
  464.                         if (np->next != NULLNTAB)
  465.                             np->next->prev = np->prev ;
  466.                         if (np->prev != NULLNTAB)
  467.                             np->prev->next = np->next ;
  468.                         else {
  469.                             Nrnbr_tab[nrhash(np->call)] = np->next ;
  470.                         }
  471.                         free((char *)np) ;    /* free the storage */
  472.                     }
  473.                 }
  474.             }
  475.             if (rp->num_routes == 0) {        /* did we free them all? */
  476.                 if (rp->next != NULLNRRTAB)
  477.                     rp->next->prev = rp->prev ;
  478.                 if (rp->prev != NULLNRRTAB)
  479.                     rp->prev->next = rp->next ;
  480.                 else
  481.                     Nrroute_tab[i] = rp->next ;
  482.  
  483.                 free((char *)rp) ;
  484.             }
  485.         }
  486.     }
  487.  
  488.     start_timer(&Obsotimer) ;
  489. }
  490.  
  491.  
  492. static struct cmds Nfcmds[] = {
  493.     "add",    donfadd,    0, 3,
  494.         "netrom nodefilter add <neighbor> <interface>",
  495.     "drop",    donfdrop,    0, 3,
  496.         "netrom nodefilter drop <neighbor> <interface>",
  497.     "mode",    donfmode,    0, 0,    NULLCHAR,
  498.     NULLCHAR,    NULLFP,    0, 0,
  499.         "nodefilter subcommands: add drop mode",
  500. } ;
  501.  
  502. /* nodefilter command multiplexer */
  503. static int
  504. donodefilter(argc,argv,p)
  505. int argc ;
  506. char *argv[] ;
  507. void *p;
  508. {
  509.     if (argc < 2) {
  510.         donfdump() ;
  511.         return 0 ;
  512.     }
  513.     return subcmd(Nfcmds,argc,argv,p) ;
  514. }
  515.  
  516. /* display a list of <callsign,interface> pairs from the filter
  517.  * list.
  518.  */
  519. static int
  520. donfdump()
  521. {
  522.     int i, column = 1 ;
  523.     struct nrnf_tab *fp ;
  524.     char buf[16] ;
  525.  
  526.     for (i = 0 ; i < NRNUMCHAINS ; i++)
  527.         for (fp = Nrnf_tab[i] ; fp != NULLNRNFTAB ; fp = fp->next) {
  528.             pax25(buf,fp->neighbor) ;
  529.             tprintf("%-7s %-8s  ",
  530.              buf,Nrifaces[fp->iface].iface->name) ;
  531.             if (column++ == 4) {
  532.                 if(tprintf("\n") == EOF)
  533.                     return 0;
  534.                 column = 1 ;
  535.             }
  536.         }
  537.  
  538.     if (column != 1)
  539.         tprintf("\n") ;
  540.  
  541.     return 0 ;
  542. }
  543.  
  544. /* add an entry to the filter table */
  545. static int
  546. donfadd(argc,argv,p)
  547. int argc ;
  548. char *argv[] ;
  549. void *p;
  550. {
  551.     char neighbor[AXALEN] ;
  552.     register int i ;
  553.  
  554.     /* format callsign */
  555.     if (setcall(neighbor,argv[1]) == -1) {
  556.         tprintf("bad neighbor callsign\n") ;
  557.         return -1 ;
  558.     }
  559.  
  560.     /* find interface */
  561.     for (i = 0 ; i < Nr_numiface ; i++)
  562.         if (!strcmp(Nrifaces[i].iface->name,argv[2]))
  563.             break ;
  564.     if (i == Nr_numiface) {
  565.         tprintf("Interface \"%s\" not found\n",argv[2]) ;
  566.         return -1 ;
  567.     }
  568.  
  569.     return nr_nfadd(neighbor,i) ;
  570. }
  571.  
  572. /* drop an entry from the filter table */
  573. static int
  574. donfdrop(argc,argv,p)
  575. int argc ;
  576. char *argv[] ;
  577. void *p;
  578. {
  579.     char neighbor[AXALEN] ;
  580.     register int i ;
  581.  
  582.     /* format neighbor callsign */
  583.     if (setcall(neighbor,argv[1]) == -1) {
  584.         tprintf("bad neighbor callsign\n") ;
  585.         return -1 ;
  586.     }
  587.  
  588.     /* find interface */
  589.     for (i = 0 ; i < Nr_numiface ; i++)
  590.         if (!strcmp(Nrifaces[i].iface->name,argv[2]))
  591.             break ;
  592.     if (i == Nr_numiface) {
  593.         tprintf("Interface \"%s\" not found\n",argv[2]) ;
  594.         return -1 ;
  595.     }
  596.  
  597.     return nr_nfdrop(neighbor,i) ;
  598. }
  599.  
  600. /* nodefilter mode subcommand */
  601. static int
  602. donfmode(argc,argv,p)
  603. int argc ;
  604. char *argv[] ;
  605. void *p;
  606. {
  607.     if (argc < 2) {
  608.         tprintf("filter mode is ") ;
  609.         switch (Nr_nfmode) {
  610.             case NRNF_NOFILTER:
  611.                 tprintf("none\n") ;
  612.                 break ;
  613.             case NRNF_ACCEPT:
  614.                 tprintf("accept\n") ;
  615.                 break ;
  616.             case NRNF_REJECT:
  617.                 tprintf("reject\n") ;
  618.                 break ;
  619.             default:
  620.                 tprintf("some strange, unknown value\n") ;
  621.         }
  622.         return 0 ;
  623.     }
  624.     
  625.     switch (argv[1][0]) {
  626.         case 'n':
  627.         case 'N':
  628.             Nr_nfmode = NRNF_NOFILTER ;
  629.             break ;
  630.         case 'a':
  631.         case 'A':
  632.             Nr_nfmode = NRNF_ACCEPT ;
  633.             break ;
  634.         case 'r':
  635.         case 'R':
  636.             Nr_nfmode = NRNF_REJECT ;
  637.             break ;
  638.         default:
  639.             tprintf("modes are: none accept reject\n") ;
  640.             return -1 ;
  641.     }
  642.  
  643.     return 0 ;
  644. }
  645.  
  646. /* netrom network packet time-to-live initializer */
  647. static int
  648. donrttl(argc, argv,p)
  649. int argc ;
  650. char *argv[] ;
  651. void *p;
  652. {
  653.     return setshort(&Nr_ttl,"Time to live",argc,argv);
  654. }
  655.  
  656. /* verbose route broadcast */
  657. static int
  658. donrverbose(argc,argv,p)
  659. int argc ;
  660. char *argv[] ;
  661. void *p;
  662. {
  663.     return setbool(&Nr_verbose,"Verbose flag",argc,argv);
  664. }
  665.  
  666. /* Initiate a NET/ROM transport connection */
  667. static int
  668. donrconnect(argc,argv,p)
  669. int argc ;
  670. char *argv[] ;
  671. void *p;
  672. {
  673.     char *np ;
  674.     struct sockaddr_nr lsocket, fsocket;
  675.     char alias[AXBUF];
  676.     struct session *sp;
  677.  
  678.     /* Get a session descriptor */
  679.     if ((sp = newsession(argv[1],NRSESSION)) == NULLSESSION) {
  680.         tprintf("Too many sessions\n") ;
  681.         return 1 ;
  682.     }
  683.  
  684.     if((sp->s = socket(AF_NETROM,SOCK_SEQPACKET,0)) == -1){
  685.         tprintf("Can't create socket\n");
  686.         keywait(NULLCHAR,1);
  687.         freesession(sp);
  688.         return 1;
  689.     }
  690.     lsocket.nr_family = AF_NETROM;
  691.     /* Set up our local username, bind would use Mycall instead */
  692.     memcpy(lsocket.nr_addr.user,Nr4user,AXALEN);
  693.     /* Putting anything else than Mycall here will not work */
  694.     memcpy(lsocket.nr_addr.node,Mycall,AXALEN);
  695.     bind(sp->s,(char *)&lsocket,sizeof(struct sockaddr_nr));
  696.  
  697.     /* See if the requested destination could be an alias, and */
  698.     /* find and use it if it is.  Otherwise assume it is an ax.25 */
  699.     /* address. */
  700.     
  701.     if (putalias(alias,argv[1],0) != -1 &&
  702.         (np = find_nralias(alias)) != NULLCHAR) {
  703.         memcpy(fsocket.nr_addr.user,np,AXALEN) ;
  704.         memcpy(fsocket.nr_addr.node,np,AXALEN) ;
  705.     } else {    /* parse ax25 callsign */
  706.         /* Only the user callsign of the remote station is never used by */
  707.         /* NET/ROM, but it is needed for the psocket() call. */
  708.         setcall(fsocket.nr_addr.user,argv[1]);
  709.         setcall(fsocket.nr_addr.node,argv[1]);
  710.     }
  711.     fsocket.nr_family = AF_NETROM;
  712.     pax25(alias,fsocket.nr_addr.node);
  713.     return tel_connect(sp, (char *)&fsocket, sizeof(struct sockaddr_nr));
  714. }
  715.  
  716. /* Reset a net/rom connection abruptly */
  717. static int
  718. donrreset(argc,argv,p)
  719. int argc;
  720. char *argv[];
  721. void *p;
  722. {
  723.     struct nr4cb *cb ;
  724.  
  725.     cb = (struct nr4cb *)htol(argv[1]);
  726.     if(!nr4valcb(cb)){
  727.         tprintf(Notval);
  728.         return 1;
  729.     }
  730.     reset_nr4(cb);
  731.     return 0;
  732. }
  733.  
  734. /* Force retransmission on a net/rom connection */
  735.  
  736. static int
  737. donrkick(argc,argv,p)
  738. int argc;
  739. char *argv[];
  740. void *p;
  741. {
  742.     struct nr4cb *cb ;
  743.  
  744.     cb = (struct nr4cb *)htol(argv[1]);
  745.  
  746.     if (kick_nr4(cb) == -1) {
  747.         tprintf(Notval);
  748.         return 1;
  749.     } else
  750.         return 0;
  751. }
  752.  
  753. /* netrom transport ACK delay timer */
  754. static int
  755. donracktime(argc, argv,p)
  756. int argc ;
  757. char *argv[] ;
  758. void *p;
  759. {
  760.     return setlong(&Nr4acktime,"Ack delay time (ms)",argc,argv);
  761. }
  762.  
  763. /* netrom transport choke timeout */
  764. static int
  765. donrchoketime(argc, argv,p)
  766. int argc ;
  767. char *argv[] ;
  768. void *p;
  769. {
  770.     return setlong(&Nr4choketime,"Choke timeout (ms)",argc,argv);
  771. }
  772.  
  773. /* netrom transport initial round trip time */
  774.  
  775. static int
  776. donrirtt(argc, argv,p)
  777. int argc ;
  778. char *argv[] ;
  779. void *p;
  780. {
  781.     return setlong(&Nr4irtt,"Initial RTT (ms)",argc,argv);
  782. }
  783.  
  784. /* netrom transport receive queue length limit.  This is the */
  785. /* threshhold at which we will CHOKE the sender. */
  786.  
  787. static int
  788. donrqlimit(argc, argv,p)
  789. int argc ;
  790. char *argv[] ;
  791. void *p;
  792. {
  793.     return setshort(&Nr4qlimit,"Queue limit (bytes)",argc,argv);
  794. }
  795.  
  796. /* Display or change our NET/ROM username */
  797. static int
  798. donruser(argc,argv,p)
  799. int argc;
  800. char *argv[];
  801. void *p;
  802. {
  803.     char buf[AXBUF];
  804.  
  805.     if(argc < 2){
  806.         pax25(buf,Nr4user);
  807.         tprintf("%s\n",buf);
  808.         return 0;
  809.     }
  810.     if(setcall(Nr4user,argv[1]) == -1)
  811.         return -1;
  812.     Nr4user[ALEN] |= E;
  813.     return 0;
  814. }
  815.  
  816. /* netrom transport maximum window.  This is the largest send and */
  817. /* receive window we may negotiate */
  818.  
  819. static int
  820. donrwindow(argc, argv,p)
  821. int argc ;
  822. char *argv[] ;
  823. void *p;
  824. {
  825.     return setshort(&Nr4window,"Window (frames)",argc,argv);
  826. }
  827.  
  828. /* netrom transport maximum retries.  This is used in connect and */
  829. /* disconnect attempts; I haven't decided what to do about actual */
  830. /* data retries yet. */
  831.  
  832. static int
  833. donrretries(argc, argv,p)
  834. int argc ;
  835. char *argv[] ;
  836. void *p;
  837. {
  838.     return setshort(&Nr4retries,"Retry limit",argc,argv);
  839. }
  840.  
  841. /* Display the status of NET/ROM connections */
  842.  
  843. static int
  844. donrstatus(argc, argv,p)
  845. int argc ;
  846. char *argv[] ;
  847. void *p;
  848. {
  849.     int i ;
  850.     struct nr4cb *cb ;
  851.     char luser[AXBUF], ruser[AXBUF], node[AXBUF] ;
  852.     
  853.     if (argc < 2) {
  854.         tprintf("     &CB Snd-W Snd-Q Rcv-Q     LUser      RUser @Node     State\n");
  855.         for (i = 0 ; i < NR4MAXCIRC ; i++) {
  856.             if ((cb = Nr4circuits[i].ccb) == NULLNR4CB)
  857.                 continue ;
  858.             pax25(luser,cb->local.user) ;
  859.             pax25(ruser,cb->remote.user) ;
  860.             pax25(node,cb->remote.node) ;
  861.             if(tprintf("%8lx   %3d %5d %5d %9s  %9s %-9s %s\n",
  862.              ptol(cb), cb->nbuffered, len_q(cb->txq),
  863.              len_p(cb->rxq), luser, ruser, node,
  864.              Nr4states[cb->state]) == EOF)
  865.                 break;
  866.         }
  867.         return 0 ;
  868.     }
  869.  
  870.     cb = (struct nr4cb *)htol(argv[1]) ;
  871.     if (!nr4valcb(cb)) {
  872.         tprintf(Notval) ;
  873.         return 1 ;
  874.     }
  875.  
  876.     donrdump(cb) ;
  877.     return 0 ;
  878. }
  879.  
  880. /* Dump one control block */
  881.  
  882. void
  883. donrdump(cb)
  884. struct nr4cb *cb ;
  885. {
  886.     char luser[AXBUF], ruser[AXBUF], node[AXBUF] ;
  887.     unsigned seq ;
  888.     struct nr4txbuf *b ;
  889.     struct timer *t ;
  890.  
  891.     pax25(luser,cb->local.user) ;
  892.     pax25(ruser,cb->remote.user) ;
  893.     pax25(node,cb->remote.node) ;
  894.  
  895.     tprintf("Local: %s %d/%d Remote: %s @ %s %d/%d State: %s\n",
  896.            luser, cb->mynum, cb->myid, ruser, node,
  897.            cb->yournum, cb->yourid, Nr4states[cb->state]) ;
  898.  
  899.     tprintf("Window: %-5u Rxpect: %-5u RxNext: %-5u RxQ: %-5d %s\n",
  900.            cb->window, uchar(cb->rxpected), uchar(cb->rxpastwin),
  901.            len_p(cb->rxq), cb->qfull ? "RxCHOKED" : "") ;
  902.  
  903.     tprintf(" Unack: %-5u Txpect: %-5u TxNext: %-5u TxQ: %-5d %s\n",
  904.            cb->nbuffered, uchar(cb->ackxpected), uchar(cb->nextosend),
  905.            len_q(cb->txq), cb->choked ? "TxCHOKED" : "") ;
  906.  
  907.     tprintf("TACK: ") ;
  908.     if (run_timer(&cb->tack))
  909.         tprintf("%lu", read_timer(&cb->tack)) ;
  910.     else
  911.         tprintf("stop") ;
  912.     tprintf("/%lu ms; ", dur_timer(&cb->tack)) ;
  913.  
  914.     tprintf("TChoke: ") ;
  915.     if (run_timer(&cb->tchoke))
  916.         tprintf("%lu", read_timer(&cb->tchoke)) ;
  917.     else
  918.         tprintf("stop") ;
  919.     tprintf("/%lu ms; ", dur_timer(&cb->tchoke)) ;
  920.  
  921.     tprintf("TCD: ") ;
  922.     if (run_timer(&cb->tcd))
  923.         tprintf("%lu", read_timer(&cb->tcd)) ;
  924.     else
  925.         tprintf("stop") ;
  926.     tprintf("/%lu ms", dur_timer(&cb->tcd)) ;
  927.  
  928.     if (run_timer(&cb->tcd))
  929.         tprintf("; Tries: %u\n", cb->cdtries) ;
  930.     else
  931.         tprintf("\n") ;
  932.  
  933.     tprintf("Backoff Level %u SRTT %ld ms Mean dev %ld ms\n",
  934.            cb->blevel, cb->srtt, cb->mdev) ;
  935.  
  936.     /* If we are connected and the send window is open, display */
  937.     /* the status of all the buffers and their timers */
  938.     
  939.     if (cb->state == NR4STCON && cb->nextosend != cb->ackxpected) {
  940.  
  941.         tprintf("TxBuffers:  Seq  Size  Tries  Timer\n") ;
  942.  
  943.         for (seq = cb->ackxpected ;
  944.              nr4between(cb->ackxpected, seq, cb->nextosend) ;
  945.              seq = (seq + 1) & NR4SEQMASK) {
  946.  
  947.             b = &cb->txbufs[seq % cb->window] ;
  948.             t = &b->tretry ;
  949.  
  950.             if(tprintf("            %3u   %3d  %5d  %lu/%lu\n",
  951.              seq, len_p(b->data), b->retries + 1,
  952.              read_timer(t), dur_timer(t))
  953.              == EOF)
  954.                 break;
  955.         }
  956.  
  957.     }
  958.  
  959. }
  960.