home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 3 / PDCD_3.iso / internet / tcpipsrc / h / if / Radio / c / AX25SUBR < prev    next >
Encoding:
Text File  |  1994-06-05  |  12.7 KB  |  429 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <time.h>
  5. #include "global.h"
  6. #include "mbuf.h"
  7. #include "timer.h"
  8. #include "ax25.h"
  9. #include "lapb.h"
  10. #include <ctype.h>
  11.  
  12. static int16 ax25hash(struct ax25_addr *);
  13.  
  14. struct ax25_cb *ax25_cb[NHASH];
  15.  
  16. /* Default AX.25 parameters */
  17. int16 t1init = 10000 / MSPTICK; /* FRACK of 10 seconds */
  18. int16 t2init = 1000 / MSPTICK;  /* 1 sec acknowledgment delay */
  19. int16 t3init = 0 / MSPTICK;     /* No keep-alive polling */
  20. int16 t4init = 300000 / MSPTICK; /* 5 minutes of no I frame tx or rx => redundant link */
  21. int16 maxframe = 1;             /* Stop and wait */
  22. int16 n2 = 10;                  /* 10 retries */
  23. int16 axwindow = 2048;          /* 2K incoming text before RNR'ing */
  24. int16 paclen = 256;             /* 256-byte I fields */
  25. int16 pthresh = 128;            /* Send polls for packets larger than this */
  26.  
  27. /* Address hash function. Exclusive-ORs each byte, ignoring
  28.  * such insignificant, annoying things as E and H bits
  29.  */
  30. static int16 ax25hash(struct ax25_addr *s)
  31. {
  32.         register char x;
  33.         register int i;
  34.         register char *cp;
  35.  
  36.         x = 0;
  37.         cp = s->call;
  38.   for (i = ALEN; i != 0; i--)
  39.                 x ^= *cp++ & 0xfe;
  40.         x ^= s->ssid & SSID;
  41.         return uchar(x) % NHASH;
  42. }
  43. /* Look up entry in hash table */
  44. struct ax25_cb *find_ax25(register struct ax25_addr *addr)
  45. {
  46.         int16 hashval;
  47.         register struct ax25_cb *axp;
  48.  
  49.         /* Find appropriate hash chain */
  50.         hashval = ax25hash(addr);
  51.  
  52.         /* Search hash chain */
  53.   for (axp = ax25_cb[hashval]; axp != NULLAX25; axp = axp->next)
  54.   {
  55.     if (addreq(&axp->addr.dest,addr))
  56.     {
  57.                         return axp;
  58.                 }
  59.         }
  60.         return NULLAX25;
  61. }
  62.  
  63. /* Remove address entry from hash table */
  64. void del_ax25(register struct ax25_cb *axp)
  65. {
  66.         int16 hashval;
  67.  
  68.         if(axp == NULLAX25)
  69.                 return;
  70.         /* Remove from hash header list if first on chain */
  71.         hashval = ax25hash(&axp->addr.dest);
  72.  
  73.         /* Remove from chain list */
  74.   if (ax25_cb[hashval] == axp)
  75.                 ax25_cb[hashval] = axp->next;
  76.   if (axp->prev != NULLAX25)
  77.                 axp->prev->next = axp->next;
  78.   if (axp->next != NULLAX25)
  79.                 axp->next->prev = axp->prev;
  80.  
  81.         /* Timers should already be stopped, but just in case... */
  82.         stop_timer(&axp->t1);
  83.         stop_timer(&axp->t2);
  84.         stop_timer(&axp->t3);
  85.         stop_timer(&axp->t4);
  86.  
  87.         /* Free allocated resources */
  88.   Window_Close(axp->terminal);
  89.         free_q(&axp->txq);
  90.         free_q(&axp->rxasm);
  91.         free_q(&axp->rxq);
  92.         free((char *)axp);
  93.  
  94. }
  95.  
  96. /* Create an ax25 control block. Allocate a new structure, if necessary,
  97.  * and fill it with all the defaults. The caller
  98.  * is still responsible for filling in the reply address
  99.  */
  100. struct ax25_cb *cr_ax25(struct ax25_addr *addr)
  101. {
  102.         register struct ax25_cb *axp;
  103.         int16 hashval;
  104.  
  105.         if(addr == NULLAXADDR)
  106.                 return NULLAX25;
  107.  
  108.         if ((axp = find_ax25(addr)) == NULLAX25)
  109.         {
  110.                 /* Not already in table; create an entry
  111.                  * and insert it at the head of the chain
  112.                  */
  113.                 /* Find appropriate hash chain */
  114.                 hashval = ax25hash(addr);
  115.                 axp = (struct ax25_cb *)calloc(1,sizeof(struct ax25_cb));
  116.                 if(axp == NULLAX25)
  117.                         return NULLAX25;
  118.                 /* Insert at beginning of chain */
  119.                 axp->prev = NULLAX25;
  120.                 axp->next = ax25_cb[hashval];
  121.                 if(axp->next != NULLAX25)
  122.                         axp->next->prev = axp;
  123.                 ax25_cb[hashval] = axp;
  124.         }
  125.         axp->terminal = Window_Open(NULL, "AX25", term_CARET | term_DONT_OPEN);
  126.         axp->maxframe = maxframe;
  127.         axp->window = axwindow;
  128.         axp->paclen = paclen;
  129.         axp->proto = V2;        /* Default, can be changed by other end */
  130.         axp->pthresh = pthresh;
  131.         axp->n2 = n2;
  132.         axp->t1.start = t1init;
  133.         axp->t1.func = recover;
  134.         axp->t1.arg = (char *)axp;
  135.  
  136.         axp->t2.start = t2init;
  137.         axp->t2.func = send_ack;
  138.         axp->t2.arg = (char *)axp;
  139.  
  140.         axp->t3.start = t3init;
  141.         axp->t3.func = pollthem;
  142.         axp->t3.arg = (char *)axp;
  143.  
  144.         axp->t4.start = t4init;
  145.         axp->t4.func = redundant;
  146.         axp->t4.arg = (char *)axp;
  147.  
  148.         axp->r_upcall = (void(*)())ax_incom;
  149.         return axp;
  150. }
  151.  
  152. /*
  153.  * setcall - convert callsign plus substation ID of the form
  154.  * "KA9Q-0" to AX.25 (shifted) address format
  155.  *   Address extension bit is left clear
  156.  *   Return -1 on error, 0 if OK
  157.  */
  158. int setcall(struct ax25_addr *out, char *call)
  159. {
  160.         int csize;
  161.         unsigned ssid;
  162.         register int i;
  163.         register char *cp,*dp;
  164.         char c;
  165.  
  166.         if(out == (struct ax25_addr *)NULL || call == NULLCHAR || *call == '\0'){
  167.                 return -1;
  168.         }
  169.         /* Find dash, if any, separating callsign from ssid
  170.          * Then compute length of callsign field and make sure
  171.          * it isn't excessive
  172.          */
  173.         dp = strchr(call,'-');
  174.         if(dp == NULLCHAR)
  175.                 csize = strlen(call);
  176.         else
  177.                 csize = dp - call;
  178.         if(csize > ALEN)
  179.                 return -1;
  180.         /* Now find and convert ssid, if any */
  181.         if(dp != NULLCHAR){
  182.                 dp++;   /* skip dash */
  183.                 ssid = atoi(dp);
  184.                 if(ssid > 15)
  185.                         return -1;
  186.         } else
  187.                 ssid = 0;
  188.         /* Copy upper-case callsign, left shifted one bit */
  189.         cp = out->call;
  190.         for(i=0;i<csize;i++){
  191.                 c = *call++;
  192.                 if(islower(c))
  193.                         c = toupper(c);
  194.                 *cp++ = c << 1;
  195.         }
  196.         /* Pad with shifted spaces if necessary */
  197.         for(;i<ALEN;i++)
  198.                 *cp++ = ' ' << 1;
  199.  
  200.         /* Insert substation ID field and set reserved bits */
  201.         out->ssid = 0x60 | (ssid << 1);
  202.         return 0;
  203. }
  204. /* Set a digipeater string in an ARP table entry */
  205. int setpath(char *out, char *in[], int cnt)
  206. {
  207.         struct ax25_addr addr;
  208.  
  209.         if(cnt == 0)
  210.                 return 0;
  211.         while(cnt-- != 0){
  212.                 setcall(&addr,*in++);
  213.                 addr.ssid &= ~E;
  214.                 out = putaxaddr(out,&addr);
  215.         }
  216.         out[-1] |= E;
  217.  
  218.         return 0;
  219. }
  220. int addreq(register struct ax25_addr *a, register struct ax25_addr *b)
  221. {
  222.         if(memcmp(a->call,b->call,ALEN) != 0)
  223.                 return 0;
  224.         if((a->ssid & SSID) != (b->ssid & SSID))
  225.                 return 0;
  226.         return 1;
  227. }
  228. /* Convert encoded AX.25 address to printable string */
  229. int pax25(char *e, struct ax25_addr *addr)
  230. {
  231.         register int i;
  232.         char c,*cp;
  233.  
  234.         cp = addr->call;
  235.         for(i=ALEN;i != 0;i--){
  236.                 c = (*cp++ >> 1) & 0x7f;
  237.                 if(c == ' ')
  238.                         break;
  239.                 *e++ = c;
  240.         }
  241.         if ((addr->ssid & SSID) != 0)
  242.                 sprintf(e,"-%d",(addr->ssid >> 1) & 0xf);       /* ssid */
  243.         else
  244.                 *e = 0;
  245.         return 0;
  246. }
  247. /* Print a string of AX.25 addresses in the form
  248.  * "KA9Q-0 [via N4HY-0,N2DSY-2]"
  249.  * Designed for use by ARP - arg is a char string
  250.  */
  251. int psax25(register char *e, register char *addr)
  252. {
  253.         int i;
  254.         struct ax25_addr axaddr;
  255.         char tmp[16];
  256.  
  257.         e[0] = '\0';    /* Give strcat a staritng point */
  258.         for(i=0;;i++){
  259.                 /* Create local copy in host-format structure */
  260.                 addr = getaxaddr(&axaddr,addr);
  261.  
  262.                 /* Create ASCII representation and append to output */
  263.                 pax25(tmp,&axaddr);
  264.                 strcat(e,tmp);
  265.  
  266.                 if(axaddr.ssid & E)
  267.                         break;
  268.                 if(i == 0)
  269.                         strcat(e," via ");
  270.                 else
  271.                         strcat(e,",");
  272.                 /* Not really necessary, but speeds up subsequent strcats */
  273.                 e += strlen(e);
  274.         }
  275.         return 0;
  276. }
  277. char *getaxaddr(register struct ax25_addr *ap, register char *cp)
  278. {
  279.         memcpy(ap->call,cp,ALEN);
  280.         cp += ALEN;
  281.         ap->ssid = *cp++;
  282.         return cp;
  283. }
  284. char *putaxaddr(register char *cp, register struct ax25_addr *ap)
  285. {
  286.         memcpy(cp,ap->call,ALEN);
  287.         cp += ALEN;
  288.         *cp++ = ap->ssid;
  289.         return cp;
  290. }
  291.  
  292. /* Convert a host-format AX.25 header into a mbuf ready for transmission */
  293. struct mbuf *htonax25(register struct ax25 *hdr, struct mbuf *data)
  294. {
  295.         struct mbuf *bp;
  296.         register char *cp;
  297.         register int16 i;
  298.  
  299.         if(hdr == (struct ax25 *)NULL || hdr->ndigis > MAXDIGIS)
  300.                 return NULLBUF;
  301.  
  302.         /* Allocate space for return buffer */
  303.         i = AXALEN * (2 + hdr->ndigis);
  304.         if((bp = pushdown(data,i)) == NULLBUF)
  305.                 return NULLBUF;
  306.  
  307.         /* Now convert */
  308.         cp = bp->data;
  309.  
  310.         hdr->dest.ssid &= ~E;   /* Dest E-bit is always off */
  311.         /* Encode command/response in C bits */
  312.         switch(hdr->cmdrsp){
  313.         case COMMAND:
  314.                 hdr->dest.ssid |= C;
  315.                 hdr->source.ssid &= ~C;
  316.                 break;
  317.         case RESPONSE:
  318.                 hdr->dest.ssid &= ~C;
  319.                 hdr->source.ssid |= C;
  320.                 break;
  321.         default:
  322.                 hdr->dest.ssid &= ~C;
  323.                 hdr->source.ssid &= ~C;
  324.                 break;
  325.         }
  326.         cp = putaxaddr(cp,&hdr->dest);
  327.  
  328.         /* Set E bit on source address if no digis */
  329.         if(hdr->ndigis == 0){
  330.                 hdr->source.ssid |= E;
  331.                 putaxaddr(cp,&hdr->source);
  332.                 return bp;
  333.         }
  334.         hdr->source.ssid &= ~E;
  335.         cp = putaxaddr(cp,&hdr->source);
  336.  
  337.         /* All but last digi get copied with E bit off */
  338.         for(i=0; i < hdr->ndigis - 1; i++){
  339.                 hdr->digis[i].ssid &= ~E;
  340.                 cp = putaxaddr(cp,&hdr->digis[i]);
  341.         }
  342.         hdr->digis[i].ssid |= E;
  343.         cp = putaxaddr(cp,&hdr->digis[i]);
  344.         return bp;
  345. }
  346. /* Convert an AX.25 ARP table entry into a host format address structure
  347.  * ready for use in transmitting a packet
  348.  */
  349. int atohax25(register struct ax25 *hdr, register char *hwaddr,
  350.              struct ax25_addr *source)
  351. {
  352.         register struct ax25_addr *axp;
  353.  
  354.         hwaddr = getaxaddr(&hdr->dest,hwaddr);  /* Destination address */
  355.         hdr->source = *source;                  /* Source address */
  356.         if(hdr->dest.ssid & E){
  357.                 /* No digipeaters */
  358.                 hdr->ndigis = 0;
  359.                 hdr->dest.ssid &= ~E;
  360.                 hdr->source.ssid |= E;
  361.                 return 2;
  362.         }
  363.         hdr->source.ssid &= ~E;
  364.         hdr->dest.ssid &= ~E;
  365.         for(axp = hdr->digis; axp < &hdr->digis[MAXDIGIS]; axp++){
  366.                 hwaddr = getaxaddr(axp,hwaddr);
  367.                 if(axp->ssid & E){
  368.                         hdr->ndigis = axp - hdr->digis + 1;
  369.                         return hdr->ndigis;
  370.                 }
  371.         }
  372.         return -1;
  373. }
  374. /* Convert a network-format AX.25 header into a host format structure
  375.  * Return -1 if error, number of addresses if OK
  376.  */
  377. int ntohax25(register struct ax25 *hdr, struct mbuf **bpp)
  378. {
  379.         register struct ax25_addr *axp;
  380.         char buf[AXALEN];
  381.  
  382.         if(pullup(bpp,buf,AXALEN) < AXALEN)
  383.                 return -1;
  384.         getaxaddr(&hdr->dest,buf);
  385.  
  386.         if(pullup(bpp,buf,AXALEN) < AXALEN)
  387.                 return -1;
  388.         getaxaddr(&hdr->source,buf);
  389.  
  390.         /* Process C bits to get command/response indication */
  391.         if((hdr->source.ssid & C) == (hdr->dest.ssid & C))
  392.                 hdr->cmdrsp = UNKNOWN;
  393.         else if(hdr->source.ssid & C)
  394.                 hdr->cmdrsp = RESPONSE;
  395.         else
  396.                 hdr->cmdrsp = COMMAND;
  397.  
  398.         hdr->ndigis = 0;
  399.         if(hdr->source.ssid & E)
  400.                 return 2;       /* No digis */
  401.  
  402.         /* Process digipeaters */
  403.         for(axp = hdr->digis;axp < &hdr->digis[MAXDIGIS]; axp++){
  404.                 if(pullup(bpp,buf,AXALEN) < AXALEN)
  405.                         return -1;
  406.                 getaxaddr(axp,buf);
  407.                 if(axp->ssid & E){      /* Last one */
  408.                         hdr->ndigis = axp - hdr->digis + 1;
  409.                         return hdr->ndigis + 2;
  410.                 }
  411.         }
  412.         return -1;      /* Too many digis */
  413. }
  414.  
  415. /* Figure out the frame type from the control field
  416.  * This is done by masking out any sequence numbers and the
  417.  * poll/final bit after determining the general class (I/S/U) of the frame
  418.  */
  419. int16 ftype(register char control)
  420. {
  421.         if((control & 1) == 0)  /* An I-frame is an I-frame... */
  422.                 return uchar(I);
  423.         if(control & 2)         /* U-frames use all except P/F bit for type */
  424.                 return (uchar(control & ~PF));
  425.         else                    /* S-frames use low order 4 bits for type */
  426.                 return (uchar(control & 0xf));
  427. }
  428.  
  429.