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