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