home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 1 / HamRadio.cdr / misc / src0131 / ax25subr.c < prev    next >
C/C++ Source or Header  |  1991-01-26  |  6KB  |  264 lines

  1. /* Low level AX.25 routines:
  2.  *  callsign conversion
  3.  *  control block management
  4.  *
  5.  * Copyright 1991 Phil Karn, KA9Q
  6.  */
  7. #include <stdio.h>
  8. #include "global.h"
  9. #include "mbuf.h"
  10. #include "timer.h"
  11. #include "ax25.h"
  12. #include "lapb.h"
  13. #include <ctype.h>
  14.  
  15. struct ax25_cb *Ax25_cb[NHASH];
  16.  
  17. /* Default AX.25 parameters */
  18. int32 T3init = 0;        /* No keep-alive polling */
  19. int16 Maxframe = 1;        /* Stop and wait */
  20. int16 N2 = 10;            /* 10 retries */
  21. int16 Axwindow = 2048;        /* 2K incoming text before RNR'ing */
  22. int16 Paclen = 256;        /* 256-byte I fields */
  23. int16 Pthresh = 128;        /* Send polls for packets larger than this */
  24. int32 Axirtt = 5000;        /* Initial round trip estimate, ms */
  25. int16 Axversion = V1;        /* Protocol version */
  26. int32 Blimit = 30;        /* Retransmission backoff limit */
  27.  
  28. /* Address hash function. Exclusive-ORs each byte, ignoring
  29.  * such insignificant, annoying things as E and H bits
  30.  */
  31. int16
  32. ax25hash(s)
  33. char *s;
  34. {
  35.     register unsigned x;
  36.     register int i;
  37.  
  38.     x = 0;
  39.     for(i=ALEN; i!=0; i--)
  40.         x ^= *s++;
  41.     x &= 0xfe;
  42.     x ^= *s & SSID;
  43.     return (int16)(uchar(x) % NHASH);
  44. }
  45. /* Look up entry in hash table */
  46. struct ax25_cb *
  47. find_ax25(addr)
  48. register char *addr;
  49. {
  50.     int16 hashval;
  51.     register struct ax25_cb *axp;
  52.  
  53.     /* Find appropriate hash chain */
  54.     hashval = ax25hash(addr);
  55.  
  56.     /* Search hash chain */
  57.     for(axp = Ax25_cb[hashval]; axp != NULLAX25; axp = axp->next){
  58.         if(addreq(axp->remote,addr)){
  59.             return axp;
  60.         }
  61.     }
  62.     return NULLAX25;
  63. }
  64.  
  65. /* Remove address entry from hash table */
  66. void
  67. del_ax25(axp)
  68. register struct ax25_cb *axp;
  69. {
  70.     int16 hashval;
  71.  
  72.     if(axp == NULLAX25)
  73.         return;
  74.     /* Remove from hash header list if first on chain */
  75.     hashval = ax25hash(axp->remote);
  76.  
  77.     /* Remove from chain list */
  78.     if(axp->prev == NULLAX25)
  79.         Ax25_cb[hashval] = axp->next;
  80.     else
  81.         axp->prev->next = axp->next;
  82.     if(axp->next != NULLAX25)
  83.         axp->next->prev = axp->prev;
  84.  
  85.     /* Timers should already be stopped, but just in case... */
  86.     stop_timer(&axp->t1);
  87.     stop_timer(&axp->t3);
  88.  
  89.     /* Free allocated resources */
  90.     free_q(&axp->txq);
  91.     free_q(&axp->rxasm);
  92.     free_q(&axp->rxq);
  93.     free((char *)axp);
  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 *
  101. cr_ax25(addr)
  102. char *addr;
  103. {
  104.     register struct ax25_cb *axp;
  105.     int16 hashval;
  106.  
  107.     if(addr == NULLCHAR)
  108.         return NULLAX25;
  109.  
  110.     if((axp = find_ax25(addr)) == NULLAX25){
  111.         /* Not already in table; create an entry
  112.          * and insert it at the head of the chain
  113.          */
  114.         /* Find appropriate hash chain */
  115.         hashval = ax25hash(addr);
  116.         axp = (struct ax25_cb *)callocw(1,sizeof(struct ax25_cb));
  117.         /* Insert at beginning of chain */
  118.         axp->next = Ax25_cb[hashval];
  119.         if(axp->next != NULLAX25)
  120.             axp->next->prev = axp;
  121.         Ax25_cb[hashval] = axp;
  122.     }
  123.     axp->user = -1;
  124.     axp->state = LAPB_DISCONNECTED;
  125.     axp->maxframe = Maxframe;
  126.     axp->window = Axwindow;
  127.     axp->paclen = Paclen;
  128.     axp->proto = Axversion;    /* Default, can be changed by other end */
  129.     axp->pthresh = Pthresh;
  130.     axp->n2 = N2;
  131.     axp->srt = Axirtt;
  132.     set_timer(&axp->t1,2*axp->srt);
  133.     axp->t1.func = recover;
  134.     axp->t1.arg = axp;
  135.  
  136.     set_timer(&axp->t3,T3init);
  137.     axp->t3.func = pollthem;
  138.     axp->t3.arg = axp;
  139.  
  140.     /* Always to a receive and state upcall as default */
  141.     axp->r_upcall = s_arcall;
  142.     axp->s_upcall = s_ascall;
  143.  
  144.     return axp;
  145. }
  146.  
  147. /*
  148.  * setcall - convert callsign plus substation ID of the form
  149.  * "KA9Q-0" to AX.25 (shifted) address format
  150.  *   Address extension bit is left clear
  151.  *   Return -1 on error, 0 if OK
  152.  */
  153. int
  154. setcall(out,call)
  155. char *out;
  156. char *call;
  157. {
  158.     int csize;
  159.     unsigned ssid;
  160.     register int i;
  161.     register char *dp;
  162.     char c;
  163.  
  164.     if(out == NULLCHAR || call == NULLCHAR || *call == '\0'){
  165.         return -1;
  166.     }
  167.     /* Find dash, if any, separating callsign from ssid
  168.      * Then compute length of callsign field and make sure
  169.      * it isn't excessive
  170.      */
  171.     dp = strchr(call,'-');
  172.     if(dp == NULLCHAR)
  173.         csize = strlen(call);
  174.     else
  175.         csize = dp - call;
  176.     if(csize > ALEN)
  177.         return -1;
  178.     /* Now find and convert ssid, if any */
  179.     if(dp != NULLCHAR){
  180.         dp++;    /* skip dash */
  181.         ssid = atoi(dp);
  182.         if(ssid > 15)
  183.             return -1;
  184.     } else
  185.         ssid = 0;
  186.     /* Copy upper-case callsign, left shifted one bit */
  187.     for(i=0;i<csize;i++){
  188.         c = *call++;
  189.         if(islower(c))
  190.             c = toupper(c);
  191.         *out++ = c << 1;
  192.     }
  193.     /* Pad with shifted spaces if necessary */
  194.     for(;i<ALEN;i++)
  195.         *out++ = ' ' << 1;
  196.     
  197.     /* Insert substation ID field and set reserved bits */
  198.     *out = 0x60 | (ssid << 1);
  199.     return 0;
  200. }
  201. int
  202. addreq(a,b)
  203. register char *a,*b;
  204. {
  205.     if(memcmp(a,b,ALEN) != 0 || ((a[ALEN] ^ b[ALEN]) & SSID) != 0)
  206.         return 0;
  207.     else
  208.         return 1;
  209. }
  210. /* Convert encoded AX.25 address to printable string */
  211. char *
  212. pax25(e,addr)
  213. char *e;
  214. char *addr;
  215. {
  216.     register int i;
  217.     char c;
  218.     char *cp;
  219.  
  220.     cp = e;
  221.     for(i=ALEN;i != 0;i--){
  222.         c = (*addr++ >> 1) & 0x7f;
  223.         if(c != ' ')
  224.             *cp++ = c;
  225.     }
  226.     if ((*addr & SSID) != 0)
  227.         sprintf(cp,"-%d",(*addr >> 1) & 0xf);    /* ssid */
  228.     else
  229.         *cp = '\0';
  230.     return e;
  231. }
  232.  
  233. /* Figure out the frame type from the control field
  234.  * This is done by masking out any sequence numbers and the
  235.  * poll/final bit after determining the general class (I/S/U) of the frame
  236.  */
  237. int16
  238. ftype(control)
  239. register int control;
  240. {
  241.     if((control & 1) == 0)    /* An I-frame is an I-frame... */
  242.         return I;
  243.     if(control & 2)        /* U-frames use all except P/F bit for type */
  244.         return (int16)(uchar(control) & ~PF);
  245.     else            /* S-frames use low order 4 bits for type */
  246.         return (int16)(uchar(control) & 0xf);
  247. }
  248.  
  249. void
  250. lapb_garbage(red)
  251. int red;
  252. {
  253.     int i;
  254.     register struct ax25_cb *axp;
  255.  
  256.     for(i=0;i<NHASH;i++){
  257.         for(axp=Ax25_cb[i];axp != NULLAX25;axp = axp->next){
  258.             mbuf_crunch(&axp->rxq);
  259.             mbuf_crunch(&axp->rxasm);
  260.         }
  261.     }
  262. }
  263.  
  264.