home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR3 / KA9Q212.ZIP / AX25CMD.C < prev    next >
C/C++ Source or Header  |  1993-07-16  |  13KB  |  575 lines

  1. /* AX25 control commands
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4.  
  5. /****************************************************************************
  6. *    $Id: ax25cmd.c 1.2 93/07/16 11:42:28 ROOT_DOS Exp $
  7. *    15 Jul 93    1.2        GT    AX25 conditional.                                *
  8. ****************************************************************************/
  9.  
  10. #include <stdio.h>
  11. #include "global.h"
  12. #include "mbuf.h"
  13. #include "timer.h"
  14. #include "proc.h"
  15. #include "iface.h"
  16. #include "ax25.h"
  17. #include "lapb.h"
  18. #include "cmdparse.h"
  19. #include "socket.h"
  20. #include "mailbox.h"
  21. #include "session.h"
  22. #include "tty.h"
  23. #include "nr4.h"
  24. #include "commands.h"
  25. #include "ip.h"
  26. #include "config.h"
  27.  
  28. #if    AX25
  29.  
  30. static int axdest __ARGS((struct iface *ifp));
  31. static int axheard __ARGS((struct iface *ifp));
  32. static void axflush __ARGS((struct iface *ifp));
  33. static int doaxflush __ARGS((int argc,char *argv[],void *p));
  34. static int doaxirtt __ARGS((int argc,char *argv[],void *p));
  35. static int doaxkick __ARGS((int argc,char *argv[],void *p));
  36. static int doaxreset __ARGS((int argc,char *argv[],void *p));
  37. static int doaxroute __ARGS((int argc,char *argv[],void *p));
  38. static int doaxstat __ARGS((int argc,char *argv[],void *p));
  39. static int doaxwindow __ARGS((int argc,char *argv[],void *p));
  40. static int doblimit __ARGS((int argc,char *argv[],void *p));
  41. static int dodigipeat __ARGS((int argc,char *argv[],void *p));
  42. static int domaxframe __ARGS((int argc,char *argv[],void *p));
  43. static int domycall __ARGS((int argc,char *argv[],void *p));
  44. static int don2 __ARGS((int argc,char *argv[],void *p));
  45. static int dopaclen __ARGS((int argc,char *argv[],void *p));
  46. static int dopthresh __ARGS((int argc,char *argv[],void *p));
  47. static int dot3 __ARGS((int argc,char *argv[],void *p));
  48. static int doversion __ARGS((int argc,char *argv[],void *p));
  49.  
  50. char *Ax25states[] = {
  51.     "",
  52.     "Disconnected",
  53.     "Listening",
  54.     "Conn pending",
  55.     "Disc pending",
  56.     "Connected",
  57.     "Recovery",
  58. };
  59.  
  60. /* Ascii explanations for the disconnect reasons listed in lapb.h under
  61.  * "reason" in ax25_cb
  62.  */
  63. char *Axreasons[] = {
  64.     "Normal",
  65.     "DM received",
  66.     "Timeout"
  67. };
  68.  
  69. static struct cmds Axcmds[] = {
  70.     "blimit",    doblimit,    0, 0, NULLCHAR,
  71.     "destlist",    doaxdest,    0, 0, NULLCHAR,
  72.     "digipeat",    dodigipeat,    0, 0, NULLCHAR,
  73.     "flush",    doaxflush,    0, 0, NULLCHAR,
  74.     "heard",    doaxheard,    0, 0, NULLCHAR,
  75.     "irtt",        doaxirtt,    0, 0, NULLCHAR,
  76.     "kick",        doaxkick,    0, 2, "ax25 kick <axcb>",
  77.     "maxframe",    domaxframe,    0, 0, NULLCHAR,
  78.     "mycall",    domycall,    0, 0, NULLCHAR,
  79.     "paclen",    dopaclen,    0, 0, NULLCHAR,
  80.     "pthresh",    dopthresh,    0, 0, NULLCHAR,
  81.     "reset",    doaxreset,    0, 2, "ax25 reset <axcb>",
  82.     "retry",    don2,        0, 0, NULLCHAR,
  83.     "route",    doaxroute,    0, 0, NULLCHAR,
  84.     "status",    doaxstat,    0, 0, NULLCHAR,
  85.     "t3",        dot3,        0, 0, NULLCHAR,
  86.     "version",    doversion,    0, 0, NULLCHAR,
  87.     "window",    doaxwindow,    0, 0, NULLCHAR,
  88.     NULLCHAR,
  89. };
  90. /* Multiplexer for top-level ax25 command */
  91. int
  92. doax25(argc,argv,p)
  93. int argc;
  94. char *argv[];
  95. void *p;
  96. {
  97.     return subcmd(Axcmds,argc,argv,p);
  98. }
  99.  
  100. int
  101. doaxheard(argc,argv,p)
  102. int argc;
  103. char *argv[];
  104. void *p;
  105. {
  106.     struct iface *ifp;
  107.  
  108.     if(argc > 1){
  109.         if((ifp = if_lookup(argv[1])) == NULLIF){
  110.             tprintf("Interface %s unknown\n",argv[1]);
  111.             return 1;
  112.         }
  113.         if(ifp->output != ax_output){
  114.             tprintf("Interface %s not AX.25\n",argv[1]);
  115.             return 1;
  116.         }
  117.         axheard(ifp);
  118.         return 0;
  119.     }
  120.     for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next){
  121.         if(ifp->output != ax_output)
  122.             continue;    /* Not an ax.25 interface */
  123.         if(axheard(ifp) == EOF)
  124.             break;
  125.     }
  126.     return 0;
  127. }
  128. static int
  129. axheard(ifp)
  130. struct iface *ifp;
  131. {
  132.     struct lq *lp;
  133.     char tmp[AXBUF];
  134.  
  135.     if(ifp->hwaddr == NULLCHAR)
  136.         return 0;
  137.     tprintf("%s:\n",ifp->name);
  138.     tprintf("Station   Last heard           Pkts\n");
  139.     for(lp = Lq;lp != NULLLQ;lp = lp->next){
  140.         if(lp->iface != ifp)
  141.             continue;
  142.         if(tprintf("%-10s%-17s%8lu\n",pax25(tmp,lp->addr),
  143.          tformat(secclock() - lp->time),lp->currxcnt) == EOF)
  144.             return EOF;
  145.     }
  146.     return 0;
  147. }
  148. int
  149. doaxdest(argc,argv,p)
  150. int argc;
  151. char *argv[];
  152. void *p;
  153. {
  154.     struct iface *ifp;
  155.  
  156.     if(argc > 1){
  157.         if((ifp = if_lookup(argv[1])) == NULLIF){
  158.             tprintf("Interface %s unknown\n",argv[1]);
  159.             return 1;
  160.         }
  161.         if(ifp->output != ax_output){
  162.             tprintf("Interface %s not AX.25\n",argv[1]);
  163.             return 1;
  164.         }
  165.         axdest(ifp);
  166.         return 0;
  167.     }
  168.     for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next){
  169.         if(ifp->output != ax_output)
  170.             continue;    /* Not an ax.25 interface */
  171.         if(axdest(ifp) == EOF)
  172.             break;
  173.     }
  174.     return 0;
  175. }
  176. static int
  177. axdest(ifp)
  178. struct iface *ifp;
  179. {
  180.     struct ld *lp;
  181.     struct lq *lq;
  182.     char tmp[AXBUF];
  183.  
  184.     if(ifp->hwaddr == NULLCHAR)
  185.         return 0;
  186.     tprintf("%s:\n",ifp->name);
  187.     tprintf("Station   Last ref         Last heard           Pkts\n");
  188.     for(lp = Ld;lp != NULLLD;lp = lp->next){
  189.         if(lp->iface != ifp)
  190.             continue;
  191.  
  192.         tprintf("%-10s%-17s",
  193.          pax25(tmp,lp->addr),tformat(secclock() - lp->time));
  194.  
  195.         if(addreq(lp->addr,ifp->hwaddr)){
  196.             /* Special case; it's our address */
  197.             tprintf("%-17s",tformat(secclock() - ifp->lastsent));
  198.         } else if((lq = al_lookup(ifp,lp->addr,0)) == NULLLQ){
  199.             tprintf("%-17s","");
  200.         } else {
  201.             tprintf("%-17s",tformat(secclock() - lq->time));
  202.         }
  203.         if(tprintf("%8lu\n",lp->currxcnt) == EOF)
  204.             return EOF;
  205.     }
  206.     return 0;
  207. }
  208. static int
  209. doaxflush(argc,argv,p)
  210. int argc;
  211. char *argv[];
  212. void *p;
  213. {
  214.     struct iface *ifp;
  215.  
  216.     for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next){
  217.         if(ifp->output != ax_output)
  218.             continue;    /* Not an ax.25 interface */
  219.         axflush(ifp);
  220.     }
  221.     return 0;
  222. }
  223. static void
  224. axflush(ifp)
  225. struct iface *ifp;
  226. {
  227.     struct lq *lp,*lp1;
  228.     struct ld *ld,*ld1;
  229.  
  230.     ifp->rawsndcnt = 0;
  231.     for(lp = Lq;lp != NULLLQ;lp = lp1){
  232.         lp1 = lp->next;
  233.         free((char *)lp);
  234.     }
  235.     Lq = NULLLQ;
  236.     for(ld = Ld;ld != NULLLD;ld = ld1){
  237.         ld1 = ld->next;
  238.         free((char *)ld);
  239.     }
  240.     Ld = NULLLD;
  241. }
  242.  
  243. static
  244. doaxreset(argc,argv,p)
  245. int argc;
  246. char *argv[];
  247. void *p;
  248. {
  249.     struct ax25_cb *axp;
  250.  
  251.     axp = (struct ax25_cb *)ltop(htol(argv[1]));
  252.     if(!ax25val(axp)){
  253.         tprintf(Notval);
  254.         return 1;
  255.     }
  256.     reset_ax25(axp);
  257.     return 0;
  258. }
  259.  
  260. /* Display AX.25 link level control blocks */
  261. static
  262. doaxstat(argc,argv,p)
  263. int argc;
  264. char *argv[];
  265. void *p;
  266. {
  267.     register struct ax25_cb *axp;
  268.     char tmp[AXBUF];
  269.  
  270.     if(argc < 2){
  271.         tprintf("    &AXB Snd-Q   Rcv-Q   Remote    State\n");
  272.         for(axp = Ax25_cb;axp != NULLAX25; axp = axp->next){
  273.             if(tprintf("%8lx %-8d%-8d%-10s%s\n",
  274.                 ptol(axp),
  275.                 len_q(axp->txq),len_p(axp->rxq),
  276.                 pax25(tmp,axp->remote),
  277.                 Ax25states[axp->state]) == EOF)
  278.                     return 0;
  279.         }
  280.         return 0;
  281.     }
  282.     axp = (struct ax25_cb *)ltop(htol(argv[1]));
  283.     if(!ax25val(axp)){
  284.         tprintf(Notval);
  285.         return 1;
  286.     }
  287.     st_ax25(axp);
  288.     return 0;
  289. }
  290. /* Dump one control block */
  291. void
  292. st_ax25(axp)
  293. register struct ax25_cb *axp;
  294. {
  295.     char tmp[AXBUF];
  296.  
  297.     if(axp == NULLAX25)
  298.         return;
  299.     tprintf("    &AXB Remote   RB V(S) V(R) Unack P Retry State\n");
  300.  
  301.     tprintf("%8lx %-9s%c%c",ptol(axp),pax25(tmp,axp->remote),
  302.      axp->flags.rejsent ? 'R' : ' ',
  303.      axp->flags.remotebusy ? 'B' : ' ');
  304.     tprintf(" %4d %4d",axp->vs,axp->vr);
  305.     tprintf(" %02u/%02u %u",axp->unack,axp->maxframe,axp->proto);
  306.     tprintf(" %02u/%02u",axp->retries,axp->n2);
  307.     tprintf(" %s\n",Ax25states[axp->state]);
  308.  
  309.     tprintf("srtt = %lu mdev = %lu ",axp->srt,axp->mdev);
  310.     tprintf("T1: ");
  311.     if(run_timer(&axp->t1))
  312.         tprintf("%lu",read_timer(&axp->t1));
  313.     else
  314.         tprintf("stop");
  315.     tprintf("/%lu ms; ",dur_timer(&axp->t1));
  316.  
  317.     tprintf("T3: ");
  318.     if(run_timer(&axp->t3))
  319.         tprintf("%lu",read_timer(&axp->t3));
  320.     else
  321.         tprintf("stop");
  322.     tprintf("/%lu ms\n",dur_timer(&axp->t3));
  323.  
  324. }
  325.  
  326. /* Display or change our AX.25 address */
  327. static
  328. domycall(argc,argv,p)
  329. int argc;
  330. char *argv[];
  331. void *p;
  332. {
  333.     char tmp[AXBUF];
  334.  
  335.     if(argc < 2){
  336.         tprintf("%s\n",pax25(tmp,Mycall));
  337.         return 0;
  338.     }
  339.     if(setcall(Mycall,argv[1]) == -1)
  340.         return -1;
  341.     return 0;
  342. }
  343.  
  344. /* Control AX.25 digipeating */
  345. static
  346. dodigipeat(argc,argv,p)
  347. int argc;
  348. char *argv[];
  349. void *p;
  350. {
  351.     return setbool(&Digipeat,"Digipeat",argc,argv);
  352. }
  353. /* Set limit on retransmission backoff */
  354. static
  355. doblimit(argc,argv,p)
  356. int argc;
  357. char *argv[];
  358. void *p;
  359. {
  360.     return setlong(&Blimit,"blimit",argc,argv);
  361. }
  362. static
  363. doversion(argc,argv,p)
  364. int argc;
  365. char *argv[];
  366. void *p;
  367. {
  368.     return setshort(&Axversion,"AX25 version",argc,argv);
  369. }
  370.  
  371. static
  372. doaxirtt(argc,argv,p)
  373. int argc;
  374. char *argv[];
  375. void *p;
  376. {
  377.     return setlong(&Axirtt,"Initial RTT (ms)",argc,argv);
  378. }
  379.  
  380. /* Set idle timer */
  381. static
  382. dot3(argc,argv,p)
  383. int argc;
  384. char *argv[];
  385. void *p;
  386. {
  387.     return setlong(&T3init,"Idle poll timer (ms)",argc,argv);
  388. }
  389.  
  390. /* Set retry limit count */
  391. static
  392. don2(argc,argv,p)
  393. int argc;
  394. char *argv[];
  395. void *p;
  396. {
  397.     return setshort(&N2,"Retry limit",argc,argv);
  398. }
  399. /* Force a retransmission */
  400. static
  401. doaxkick(argc,argv,p)
  402. int argc;
  403. char *argv[];
  404. void *p;
  405. {
  406.     struct ax25_cb *axp;
  407.  
  408.     axp = (struct ax25_cb *)ltop(htol(argv[1]));
  409.     if(!ax25val(axp)){
  410.         tprintf(Notval);
  411.         return 1;
  412.     }
  413.     kick_ax25(axp);
  414.     return 0;
  415. }
  416. /* Set maximum number of frames that will be allowed in flight */
  417. static
  418. domaxframe(argc,argv,p)
  419. int argc;
  420. char *argv[];
  421. void *p;
  422. {
  423.     return setshort(&Maxframe,"Window size (frames)",argc,argv);
  424. }
  425.  
  426. /* Set maximum length of I-frame data field */
  427. static
  428. dopaclen(argc,argv,p)
  429. int argc;
  430. char *argv[];
  431. void *p;
  432. {
  433.     return setshort(&Paclen,"Max frame length (bytes)",argc,argv);
  434. }
  435. /* Set size of I-frame above which polls will be sent after a timeout */
  436. static
  437. dopthresh(argc,argv,p)
  438. int argc;
  439. char *argv[];
  440. void *p;
  441. {
  442.     return setshort(&Pthresh,"Poll threshold (bytes)",argc,argv);
  443. }
  444.  
  445. /* Set high water mark on receive queue that triggers RNR */
  446. static
  447. doaxwindow(argc,argv,p)
  448. int argc;
  449. char *argv[];
  450. void *p;
  451. {
  452.     return setshort(&Axwindow,"AX25 receive window (bytes)",argc,argv);
  453. }
  454. /* End of ax25 subcommands */
  455.  
  456. /* Initiate interactive AX.25 connect to remote station */
  457. int
  458. doconnect(argc,argv,p)
  459. int argc;
  460. char *argv[];
  461. void *p;
  462. {
  463.     struct sockaddr_ax fsocket;
  464.     struct session *sp;
  465.     int ndigis,i;
  466.     char digis[MAXDIGIS][AXALEN];
  467.     char target[AXALEN];
  468.  
  469.     /* If digipeaters are given, put them in the routing table */
  470.     if(argc > 3){
  471.         setcall(target,argv[2]);
  472.         ndigis = argc - 3;
  473.         if(ndigis > MAXDIGIS){
  474.             tprintf("Too many digipeaters\n");
  475.             return 1;
  476.         }
  477.         for(i=0;i<ndigis;i++){
  478.             if(setcall(digis[i],argv[i+3]) == -1){
  479.                 tprintf("Bad digipeater %s\n",argv[i+3]);
  480.                 return 1;
  481.             }
  482.         }
  483.         if(ax_add(target,AX_LOCAL,digis,ndigis) == NULLAXR){
  484.             tprintf("Route add failed\n");
  485.             return 1;
  486.         }
  487.     }
  488.     /* Allocate a session descriptor */
  489.     if((sp = newsession(argv[2],AX25TNC)) == NULLSESSION){
  490.         tprintf("Too many sessions\n");
  491.         return 1;
  492.     }
  493.     if((sp->s = socket(AF_AX25,SOCK_STREAM,0)) == -1){
  494.         tprintf("Can't create socket\n");
  495.         freesession(sp);
  496.         keywait(NULLCHAR,1);
  497.         return 1;
  498.     }
  499.     fsocket.sax_family = AF_AX25;
  500.     setcall(fsocket.ax25_addr,argv[2]);
  501.     strncpy(fsocket.iface,argv[1],ILEN);
  502.     return tel_connect(sp, (char *)&fsocket, sizeof(struct sockaddr_ax));
  503. }
  504.  
  505. /* Display and modify AX.25 routing table */
  506. static int
  507. doaxroute(argc,argv,p)
  508. int argc;
  509. char *argv[];
  510. void *p;
  511. {
  512.     char tmp[AXBUF];
  513.     int i,ndigis;
  514.     register struct ax_route *axr;
  515.     char target[AXALEN],digis[MAXDIGIS][AXALEN];
  516.  
  517.     if(argc < 2){
  518.         tprintf("Target    Type   Digipeaters\n");
  519.         for(axr = Ax_routes;axr != NULLAXR;axr = axr->next){
  520.             tprintf("%-10s%-6s",pax25(tmp,axr->target),
  521.              axr->type == AX_LOCAL ? "Local":"Auto");
  522.             for(i=0;i<axr->ndigis;i++){
  523.                 tprintf(" %s",pax25(tmp,axr->digis[i]));
  524.             }
  525.             if(tprintf("\n") == EOF)
  526.                 return 0;
  527.         }
  528.         return 0;
  529.     }
  530.     if(argc < 3){
  531.         tprintf("Usage: ax25 route add <target> [digis...]\n");
  532.         tprintf("       ax25 route drop <target>\n");
  533.         return 1;
  534.     }
  535.     if(setcall(target,argv[2]) == -1){
  536.         tprintf("Bad target %s\n",argv[2]);
  537.         return 1;
  538.     }
  539.     switch(argv[1][0]){
  540.     case 'a':    /* Add route */
  541.         if(argc < 3){
  542.             tprintf("Usage: ax25 route add <target> [digis...]\n");
  543.             return 1;
  544.         }
  545.         ndigis = argc - 3;
  546.         if(ndigis > MAXDIGIS){
  547.             tprintf("Too many digipeaters\n");
  548.             return 1;
  549.         }
  550.         for(i=0;i<ndigis;i++){
  551.             if(setcall(digis[i],argv[i+3]) == -1){
  552.                 tprintf("Bad digipeater %s\n",argv[i+3]);
  553.                 return 1;
  554.             }
  555.         }
  556.         if(ax_add(target,AX_LOCAL,digis,ndigis) == NULLAXR){
  557.             tprintf("Failed\n");
  558.             return 1;
  559.         }
  560.         break;
  561.     case 'd':    /* Drop route */
  562.         if(ax_drop(target) == -1){
  563.             tprintf("Not in table\n");
  564.             return 1;
  565.         }
  566.         break;
  567.     default:
  568.         tprintf("Unknown command %s\n",argv[1]);
  569.         return 1;
  570.     }
  571.     return 0;
  572. }
  573.  
  574. #endif    /* AX25 */
  575.