home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 3 / hamradioversion3.0examsandprograms1992.iso / misc / 9q920411 / ax25cmd.c < prev    next >
C/C++ Source or Header  |  1992-04-09  |  12KB  |  564 lines

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