home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / hamradio / s920603.zip / NRCMD.C < prev    next >
C/C++ Source or Header  |  1992-05-02  |  23KB  |  962 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.             printf("%-16s  ",buf) ;
  149.             if (column++ == 4) {
  150.                 if(printf("\n") == EOF)
  151.                     return 0;
  152.                 column = 1 ;
  153.             }
  154.         }
  155.  
  156.     if (column != 1)
  157.         printf("\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.         printf ("bad destination name\n") ;
  177.         return -1 ;
  178.     }
  179.         
  180.     if ((rp = find_nrroute(dest)) == NULLNRRTAB) {
  181.         printf("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(printf("%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.             printf ("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.         printf("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.         printf("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.         printf("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.         printf("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.         printf("bad destination callsign\n") ;
  294.         return -1 ;
  295.     }
  296.     if (setcall(neighbor,argv[2]) == -1) {
  297.         printf("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.         printf("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.         printf("Attach netrom interface first\n") ;
  326.         return 1 ;
  327.     }
  328.     
  329.     if (Nr_numiface >= NRNUMIFACE) {
  330.         printf("Only %d net/rom interfaces available\n",NRNUMIFACE) ;
  331.         return 1 ;
  332.     }
  333.     
  334.     if((ifp = if_lookup(argv[1])) == NULLIF){
  335.         printf("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.             printf("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.         printf("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.         printf("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.         printf("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.         printf("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.             printf("%-7s %-8s  ",
  530.              buf,Nrifaces[fp->iface].iface->name) ;
  531.             if (column++ == 4) {
  532.                 if(printf("\n") == EOF)
  533.                     return 0;
  534.                 column = 1 ;
  535.             }
  536.         }
  537.  
  538.     if (column != 1)
  539.         printf("\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.         printf("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.         printf("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.         printf("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.         printf("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.         printf("filter mode is ") ;
  609.         switch (Nr_nfmode) {
  610.             case NRNF_NOFILTER:
  611.                 printf("none\n") ;
  612.                 break ;
  613.             case NRNF_ACCEPT:
  614.                 printf("accept\n") ;
  615.                 break ;
  616.             case NRNF_REJECT:
  617.                 printf("reject\n") ;
  618.                 break ;
  619.             default:
  620.                 printf("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.             printf("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.     int s;
  678.  
  679.     /* Get a session descriptor */
  680.     if ((sp = newsession(argv[1],NRSESSION,1)) == NULLSESSION) {
  681.         printf("Too many sessions\n") ;
  682.         return 1 ;
  683.     }
  684.  
  685.     if((s = socket(AF_NETROM,SOCK_SEQPACKET,0)) == -1){
  686.         printf("Can't create socket\n");
  687.         keywait(NULLCHAR,1);
  688.         freesession(sp);
  689.         return 1;
  690.     }
  691.     lsocket.nr_family = AF_NETROM;
  692.     /* Set up our local username, bind would use Mycall instead */
  693.     memcpy(lsocket.nr_addr.user,Nr4user,AXALEN);
  694.     /* Putting anything else than Mycall here will not work */
  695.     memcpy(lsocket.nr_addr.node,Mycall,AXALEN);
  696.     bind(s,(char *)&lsocket,sizeof(struct sockaddr_nr));
  697.  
  698.     /* See if the requested destination could be an alias, and */
  699.     /* find and use it if it is.  Otherwise assume it is an ax.25 */
  700.     /* address. */
  701.     
  702.     if (putalias(alias,argv[1],0) != -1 &&
  703.         (np = find_nralias(alias)) != NULLCHAR) {
  704.         memcpy(fsocket.nr_addr.user,np,AXALEN) ;
  705.         memcpy(fsocket.nr_addr.node,np,AXALEN) ;
  706.     } else {    /* parse ax25 callsign */
  707.         /* Only the user callsign of the remote station is never used by */
  708.         /* NET/ROM, but it is needed for the psocket() call. */
  709.         setcall(fsocket.nr_addr.user,argv[1]);
  710.         setcall(fsocket.nr_addr.node,argv[1]);
  711.     }
  712.     fsocket.nr_family = AF_NETROM;
  713.     pax25(alias,fsocket.nr_addr.node);
  714.     sp->network = fdopen(s,"r+t");
  715.     return tel_connect(sp, (char *)&fsocket, sizeof(struct sockaddr_nr));
  716. }
  717.  
  718. /* Reset a net/rom connection abruptly */
  719. static int
  720. donrreset(argc,argv,p)
  721. int argc;
  722. char *argv[];
  723. void *p;
  724. {
  725.     struct nr4cb *cb ;
  726.  
  727.     cb = (struct nr4cb *)htol(argv[1]);
  728.     if(!nr4valcb(cb)){
  729.         printf(Notval);
  730.         return 1;
  731.     }
  732.     reset_nr4(cb);
  733.     return 0;
  734. }
  735.  
  736. /* Force retransmission on a net/rom connection */
  737.  
  738. static int
  739. donrkick(argc,argv,p)
  740. int argc;
  741. char *argv[];
  742. void *p;
  743. {
  744.     struct nr4cb *cb ;
  745.  
  746.     cb = (struct nr4cb *)htol(argv[1]);
  747.  
  748.     if (kick_nr4(cb) == -1) {
  749.         printf(Notval);
  750.         return 1;
  751.     } else
  752.         return 0;
  753. }
  754.  
  755. /* netrom transport ACK delay timer */
  756. static int
  757. donracktime(argc, argv,p)
  758. int argc ;
  759. char *argv[] ;
  760. void *p;
  761. {
  762.     return setlong(&Nr4acktime,"Ack delay time (ms)",argc,argv);
  763. }
  764.  
  765. /* netrom transport choke timeout */
  766. static int
  767. donrchoketime(argc, argv,p)
  768. int argc ;
  769. char *argv[] ;
  770. void *p;
  771. {
  772.     return setlong(&Nr4choketime,"Choke timeout (ms)",argc,argv);
  773. }
  774.  
  775. /* netrom transport initial round trip time */
  776.  
  777. static int
  778. donrirtt(argc, argv,p)
  779. int argc ;
  780. char *argv[] ;
  781. void *p;
  782. {
  783.     return setlong(&Nr4irtt,"Initial RTT (ms)",argc,argv);
  784. }
  785.  
  786. /* netrom transport receive queue length limit.  This is the */
  787. /* threshhold at which we will CHOKE the sender. */
  788.  
  789. static int
  790. donrqlimit(argc, argv,p)
  791. int argc ;
  792. char *argv[] ;
  793. void *p;
  794. {
  795.     return setshort(&Nr4qlimit,"Queue limit (bytes)",argc,argv);
  796. }
  797.  
  798. /* Display or change our NET/ROM username */
  799. static int
  800. donruser(argc,argv,p)
  801. int argc;
  802. char *argv[];
  803. void *p;
  804. {
  805.     char buf[AXBUF];
  806.  
  807.     if(argc < 2){
  808.         pax25(buf,Nr4user);
  809.         printf("%s\n",buf);
  810.         return 0;
  811.     }
  812.     if(setcall(Nr4user,argv[1]) == -1)
  813.         return -1;
  814.     Nr4user[ALEN] |= E;
  815.     return 0;
  816. }
  817.  
  818. /* netrom transport maximum window.  This is the largest send and */
  819. /* receive window we may negotiate */
  820.  
  821. static int
  822. donrwindow(argc, argv,p)
  823. int argc ;
  824. char *argv[] ;
  825. void *p;
  826. {
  827.     return setshort(&Nr4window,"Window (frames)",argc,argv);
  828. }
  829.  
  830. /* netrom transport maximum retries.  This is used in connect and */
  831. /* disconnect attempts; I haven't decided what to do about actual */
  832. /* data retries yet. */
  833.  
  834. static int
  835. donrretries(argc, argv,p)
  836. int argc ;
  837. char *argv[] ;
  838. void *p;
  839. {
  840.     return setshort(&Nr4retries,"Retry limit",argc,argv);
  841. }
  842.  
  843. /* Display the status of NET/ROM connections */
  844.  
  845. static int
  846. donrstatus(argc, argv,p)
  847. int argc ;
  848. char *argv[] ;
  849. void *p;
  850. {
  851.     int i ;
  852.     struct nr4cb *cb ;
  853.     char luser[AXBUF], ruser[AXBUF], node[AXBUF] ;
  854.     
  855.     if (argc < 2) {
  856.         printf("     &CB Snd-W Snd-Q Rcv-Q     LUser      RUser @Node     State\n");
  857.         for (i = 0 ; i < NR4MAXCIRC ; i++) {
  858.             if ((cb = Nr4circuits[i].ccb) == NULLNR4CB)
  859.                 continue ;
  860.             pax25(luser,cb->local.user) ;
  861.             pax25(ruser,cb->remote.user) ;
  862.             pax25(node,cb->remote.node) ;
  863.             if(printf("%8lx   %3d %5d %5d %9s  %9s %-9s %s\n",
  864.              ptol(cb), cb->nbuffered, len_q(cb->txq),
  865.              len_p(cb->rxq), luser, ruser, node,
  866.              Nr4states[cb->state]) == EOF)
  867.                 break;
  868.         }
  869.         return 0 ;
  870.     }
  871.  
  872.     cb = (struct nr4cb *)htol(argv[1]) ;
  873.     if (!nr4valcb(cb)) {
  874.         printf(Notval) ;
  875.         return 1 ;
  876.     }
  877.  
  878.     donrdump(cb) ;
  879.     return 0 ;
  880. }
  881.  
  882. /* Dump one control block */
  883.  
  884. void
  885. donrdump(cb)
  886. struct nr4cb *cb ;
  887. {
  888.     char luser[AXBUF], ruser[AXBUF], node[AXBUF] ;
  889.     unsigned seq ;
  890.     struct nr4txbuf *b ;
  891.     struct timer *t ;
  892.  
  893.     pax25(luser,cb->local.user) ;
  894.     pax25(ruser,cb->remote.user) ;
  895.     pax25(node,cb->remote.node) ;
  896.  
  897.     printf("Local: %s %d/%d Remote: %s @ %s %d/%d State: %s\n",
  898.            luser, cb->mynum, cb->myid, ruser, node,
  899.            cb->yournum, cb->yourid, Nr4states[cb->state]) ;
  900.  
  901.     printf("Window: %-5u Rxpect: %-5u RxNext: %-5u RxQ: %-5d %s\n",
  902.            cb->window, uchar(cb->rxpected), uchar(cb->rxpastwin),
  903.            len_p(cb->rxq), cb->qfull ? "RxCHOKED" : "") ;
  904.  
  905.     printf(" Unack: %-5u Txpect: %-5u TxNext: %-5u TxQ: %-5d %s\n",
  906.            cb->nbuffered, uchar(cb->ackxpected), uchar(cb->nextosend),
  907.            len_q(cb->txq), cb->choked ? "TxCHOKED" : "") ;
  908.  
  909.     printf("TACK: ") ;
  910.     if (run_timer(&cb->tack))
  911.         printf("%lu", read_timer(&cb->tack)) ;
  912.     else
  913.         printf("stop") ;
  914.     printf("/%lu ms; ", dur_timer(&cb->tack)) ;
  915.  
  916.     printf("TChoke: ") ;
  917.     if (run_timer(&cb->tchoke))
  918.         printf("%lu", read_timer(&cb->tchoke)) ;
  919.     else
  920.         printf("stop") ;
  921.     printf("/%lu ms; ", dur_timer(&cb->tchoke)) ;
  922.  
  923.     printf("TCD: ") ;
  924.     if (run_timer(&cb->tcd))
  925.         printf("%lu", read_timer(&cb->tcd)) ;
  926.     else
  927.         printf("stop") ;
  928.     printf("/%lu ms", dur_timer(&cb->tcd)) ;
  929.  
  930.     if (run_timer(&cb->tcd))
  931.         printf("; Tries: %u\n", cb->cdtries) ;
  932.     else
  933.         printf("\n") ;
  934.  
  935.     printf("Backoff Level %u SRTT %ld ms Mean dev %ld ms\n",
  936.            cb->blevel, cb->srtt, cb->mdev) ;
  937.  
  938.     /* If we are connected and the send window is open, display */
  939.     /* the status of all the buffers and their timers */
  940.     
  941.     if (cb->state == NR4STCON && cb->nextosend != cb->ackxpected) {
  942.  
  943.         printf("TxBuffers:  Seq  Size  Tries  Timer\n") ;
  944.  
  945.         for (seq = cb->ackxpected ;
  946.              nr4between(cb->ackxpected, seq, cb->nextosend) ;
  947.              seq = (seq + 1) & NR4SEQMASK) {
  948.  
  949.             b = &cb->txbufs[seq % cb->window] ;
  950.             t = &b->tretry ;
  951.  
  952.             if(printf("            %3u   %3d  %5d  %lu/%lu\n",
  953.              seq, len_p(b->data), b->retries + 1,
  954.              read_timer(t), dur_timer(t))
  955.              == EOF)
  956.                 break;
  957.         }
  958.  
  959.     }
  960.  
  961. }
  962.