home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / telecomm / ka9q_src / ax25subr.c < prev    next >
C/C++ Source or Header  |  1988-11-29  |  13KB  |  573 lines

  1. #include "global.h"
  2. #include "mbuf.h"
  3. #include "timer.h"
  4. #include "ax25.h"
  5. #ifdef    NRS
  6. #include "netrom.h"
  7. #endif
  8. #include "lapb.h"
  9. #include <ctype.h>
  10.  
  11. struct ax25_cb *ax25_cb[NHASH];
  12.  
  13. /* Default AX.25 parameters */
  14. int16 t1init = 10;    /* FRACK of 10 seconds */
  15. int16 t2init = 1;    /* 1 sec acknowledgment delay */
  16. int16 t3init = 0;    /* No keep-alive polling */
  17. int16 maxframe = 1;    /* Stop and wait */
  18. int16 n2 = 10;        /* 10 retries */
  19. int16 axwindow = 2048;    /* 2K incoming text before RNR'ing */
  20. int16 paclen = 256;    /* 256-byte I fields */
  21.  
  22.  
  23. /* Address hash function. Exclusive-ORs each byte, ignoring
  24.  * such insignificant, annoying things as E and H bits
  25.  */
  26. static
  27. int16
  28. ax25hash(s)
  29. struct ax25_addr *s;
  30. {
  31.     register int16 x;
  32.     register int i;
  33.     register char *cp;
  34.  
  35.     x = 0;
  36.     cp = s->call;
  37.     for(i=0; i<ALEN; i++)
  38.         x ^= *cp++ & 0xfe;
  39.     x ^= s->ssid & SSID;
  40.     return (x & 0xff) % NHASH;
  41. }
  42. /* Look up entry in hash table */
  43. struct ax25_cb *
  44. find_ax25(addr)
  45. register struct ax25_addr *addr;
  46. {
  47.     int16 hashval;
  48.     register struct ax25_cb *axp;
  49.     char i_state;
  50.  
  51.     /* Find appropriate hash chain */
  52.     hashval = ax25hash(addr);
  53.  
  54.     /* Search hash chain */
  55.     i_state = disable();
  56.     for(axp = ax25_cb[hashval]; axp != NULLAX25; axp = axp->next){
  57.         if(addreq(&axp->addr.dest,addr)){
  58.             restore(i_state);
  59.             return axp;
  60.         }
  61.     }
  62.     restore(i_state);
  63.     return NULLAX25;
  64. }
  65.  
  66. /* Remove address entry from hash table */
  67. del_ax25(axp)
  68. register struct ax25_cb *axp;
  69. {
  70.     int16 hashval;
  71.     char i_state;
  72.  
  73.     if(axp == NULLAX25)
  74.         return;
  75.     /* Remove from hash header list if first on chain */
  76.     hashval = ax25hash(&axp->addr.dest);
  77.     i_state = disable();
  78.  
  79.     /* Remove from chain list */
  80.     if(ax25_cb[hashval] == axp)
  81.         ax25_cb[hashval] = axp->next;
  82.     if(axp->prev != NULLAX25)
  83.         axp->prev->next = axp->next;
  84.     if(axp->next != NULLAX25)
  85.         axp->next->prev = axp->prev;
  86.  
  87.     /* Timers should already be stopped, but just in case... */
  88.     stop_timer(&axp->t1);
  89.     stop_timer(&axp->t2);
  90.     stop_timer(&axp->t3);
  91.  
  92.     /* Free allocated resources */
  93.     free_q(&axp->txq);
  94.     free_q(&axp->rxasm);
  95.     free_q(&axp->rxq);
  96.     free((char *)axp);
  97.  
  98.     restore(i_state);
  99. }
  100.  
  101. /* Create an ax25 control block. Allocate a new structure, if necessary,
  102.  * and fill it with all the defaults. The caller
  103.  * is still responsible for filling in the reply address
  104.  */
  105. struct ax25_cb *
  106. cr_ax25(addr)
  107. struct ax25_addr *addr;
  108. {
  109.     void recover(),send_ack(),pollthem(),ax_incom();
  110.     register struct ax25_cb *axp;
  111.     int16 hashval;
  112.     char i_state;
  113.  
  114.     if(addr == NULLAXADDR)
  115.         return NULLAX25;
  116.  
  117.     if((axp = find_ax25(addr)) == NULLAX25){
  118.         /* Not already in table; create an entry
  119.          * and insert it at the head of the chain
  120.          */
  121.         /* Find appropriate hash chain */
  122.         hashval = ax25hash(addr);
  123.         i_state = disable();
  124.         axp = (struct ax25_cb *)calloc(1,sizeof(struct ax25_cb));
  125.         if(axp == NULLAX25)
  126.             return NULLAX25;
  127.         /* Insert at beginning of chain */
  128.         axp->prev = NULLAX25;
  129.         axp->next = ax25_cb[hashval];
  130.         if(axp->next != NULLAX25)
  131.             axp->next->prev = axp;
  132.         ax25_cb[hashval] = axp;
  133.         restore(i_state);
  134.     }
  135.     axp->maxframe = maxframe;
  136.     axp->window = axwindow;
  137.     axp->paclen = paclen;
  138.     axp->proto = V1;
  139.     axp->n2 = n2;
  140.     axp->t1.start = t1init;
  141.     axp->t1.func = recover;
  142.     axp->t1.arg = (char *)axp;
  143.  
  144.     axp->t2.start = t2init;
  145.     axp->t2.func = send_ack;
  146.     axp->t2.arg = (char *)axp;
  147.  
  148.     axp->t3.start = t3init;
  149.     axp->t3.func = pollthem;
  150.     axp->t3.arg = (char *)axp;
  151.  
  152.     axp->r_upcall = ax_incom;
  153.     return axp;
  154. }
  155.  
  156. /*
  157.  * setcall - convert callsign plus substation ID of the form
  158.  * "KA9Q-0" to AX.25 (shifted) address format
  159.  *   Address extension bit is left clear
  160.  *   Return -1 on error, 0 if OK
  161.  */
  162. int
  163. setcall(out,call)
  164. struct ax25_addr *out;
  165. char *call;
  166. {
  167.     int csize;
  168.     unsigned ssid;
  169.     register int i;
  170.     register char *cp,*dp;
  171.     char c;
  172.  
  173.     if(out == (struct ax25_addr *)0 || call == NULLCHAR || *call == '\0'){
  174.         return -1;
  175.     }
  176.     /* Find dash, if any, separating callsign from ssid
  177.      * Then compute length of callsign field and make sure
  178.      * it isn't excessive
  179.      */
  180.     dp = index(call,'-');
  181.     if(dp == NULLCHAR)
  182.         csize = strlen(call);
  183.     else
  184.         csize = dp - call;
  185.     if(csize > ALEN)
  186.         return -1;
  187.     /* Now find and convert ssid, if any */
  188.     if(dp != NULLCHAR){
  189.         dp++;    /* skip dash */
  190.         ssid = atoi(dp);
  191.         if(ssid > 15)
  192.             return -1;
  193.     } else
  194.         ssid = 0;
  195.     /* Copy upper-case callsign, left shifted one bit */
  196.     cp = out->call;
  197.     for(i=0;i<csize;i++){
  198.         c = *call++;
  199.         if(islower(c))
  200.             c = toupper(c);
  201.         *cp++ = c << 1;
  202.     }
  203.     /* Pad with shifted spaces if necessary */
  204.     for(;i<ALEN;i++)
  205.         *cp++ = ' ' << 1;
  206.     
  207.     /* Insert substation ID field and set reserved bits */
  208.     out->ssid = 0x60 | (ssid << 1);
  209.     return 0;
  210. }
  211. /* Set a digipeater string in an ARP table entry */
  212. setpath(out,in,cnt)
  213. char *out;    /* Target char array containing addresses in net form */
  214. char *in[];    /* Input array of tokenized callsigns in ASCII */
  215. int cnt;    /* Number of callsigns in array */
  216. {
  217.     struct ax25_addr addr;
  218.     char *putaxaddr();
  219.  
  220.     if(cnt == 0)
  221.         return;
  222.     while(cnt-- != 0){
  223.         setcall(&addr,*in++);
  224.         addr.ssid &= ~E;
  225.         out = putaxaddr(out,&addr);
  226.     }
  227.     out[-1] |= E;
  228. }
  229. addreq(a,b)
  230. register struct ax25_addr *a,*b;
  231. {
  232.     if(memcmp(a->call,b->call,ALEN) != 0)
  233.         return 0;
  234.     if((a->ssid & SSID) != (b->ssid & SSID))
  235.         return 0;
  236.     return 1;
  237. }
  238. /* Convert encoded AX.25 address to printable string */
  239. pax25(e,addr)
  240. char *e;
  241. struct ax25_addr *addr;
  242. {
  243.     register int i;
  244.     char c,*cp;
  245.  
  246.     cp = addr->call;
  247.     for(i=ALEN;i != 0;i--){
  248.         c = (*cp++ >> 1) & 0x7f;
  249.         if(c == ' ')
  250.             break;
  251.         *e++ = c;
  252.     }
  253.     if ((addr->ssid & SSID) != 0)
  254.         sprintf(e,"-%d",(addr->ssid >> 1) & 0xf);    /* ssid */
  255.     else
  256.         *e = 0;
  257. }
  258. /* Print a string of AX.25 addresses in the form
  259.  * "KA9Q-0 [via N4HY-0,N2DSY-2]"
  260.  * Designed for use by ARP - arg is a char string
  261.  */
  262. psax25(e,addr)
  263. register char *e;
  264. register char *addr;
  265. {
  266.     int i;
  267.     struct ax25_addr axaddr;
  268.     char tmp[16];
  269.     char *getaxaddr();
  270.  
  271.     e[0] = '\0';    /* Give strcat a starting point */
  272.     for(i=0;;i++){
  273.         /* Create local copy in host-format structure */
  274.         addr = getaxaddr(&axaddr,addr);
  275.  
  276.         /* Create ASCII representation and append to output */
  277.         pax25(tmp,&axaddr);
  278.         strcat(e,tmp);
  279.  
  280.         if(axaddr.ssid & E)
  281.             break;
  282.         if(i == 0)
  283.             strcat(e," via ");
  284.         else
  285.             strcat(e,",");
  286.         /* Not really necessary, but speeds up subsequent strcats */
  287.         e += strlen(e);
  288.     }
  289. }
  290. static
  291. char *
  292. getaxaddr(ap,cp)
  293. register struct ax25_addr *ap;
  294. register char *cp;
  295. {
  296.     memcpy(ap->call,cp,ALEN);
  297.     cp += ALEN;
  298.     ap->ssid = *cp++;
  299.     return cp;
  300. }
  301. static char *
  302. putaxaddr(cp,ap)
  303. register char *cp;
  304. register struct ax25_addr *ap;
  305. {
  306.     memcpy(cp,ap->call,ALEN);
  307.     cp += ALEN;
  308.     *cp++ = ap->ssid;
  309.     return cp;
  310. }
  311.  
  312. /* Convert a host-format AX.25 header into a mbuf ready for transmission */
  313. struct mbuf *
  314. htonax25(hdr)
  315. register struct ax25 *hdr;
  316. {
  317.     struct mbuf *rbuf;
  318.     register char *cp;
  319.     register int16 i;
  320.  
  321.     if(hdr == (struct ax25 *)0 || hdr->ndigis > MAXDIGIS)
  322.         return NULLBUF;
  323.  
  324.     /* Allocate space for return buffer */
  325.     i = AXALEN * (2 + hdr->ndigis);
  326.     if((rbuf = alloc_mbuf(i)) == NULLBUF)
  327.         return NULLBUF;
  328.     rbuf->cnt = i;
  329.  
  330.     /* Now convert */
  331.     cp = rbuf->data;
  332.  
  333.     hdr->dest.ssid &= ~E;    /* Dest E-bit is always off */
  334.     /* Encode command/response in C bits */
  335.     switch(hdr->cmdrsp){
  336.     case COMMAND:
  337.         hdr->dest.ssid |= C;
  338.         hdr->source.ssid &= ~C;
  339.         break;
  340.     case RESPONSE:
  341.         hdr->dest.ssid &= ~C;
  342.         hdr->source.ssid |= C;
  343.         break;
  344.     default:
  345.         hdr->dest.ssid &= ~C;
  346.         hdr->source.ssid &= ~C;
  347.         break;
  348.     }
  349.     cp = putaxaddr(cp,&hdr->dest);
  350.  
  351.     /* Set E bit on source address if no digis */
  352.     if(hdr->ndigis == 0){
  353.         hdr->source.ssid |= E;
  354.         putaxaddr(cp,&hdr->source);
  355.         return rbuf;
  356.     }
  357.     hdr->source.ssid &= ~E;
  358.     cp = putaxaddr(cp,&hdr->source);
  359.  
  360.     /* All but last digi get copied with E bit off */
  361.     for(i=0; i < hdr->ndigis - 1; i++){
  362.         hdr->digis[i].ssid &= ~E;
  363.         cp = putaxaddr(cp,&hdr->digis[i]);
  364.     }
  365.     hdr->digis[i].ssid |= E;
  366.     cp = putaxaddr(cp,&hdr->digis[i]);
  367.     return rbuf;
  368. }
  369. /* Convert an AX.25 ARP table entry into a host format address structure
  370.  * ready for use in transmitting a packet
  371.  */
  372. int
  373. atohax25(hdr,hwaddr,source)
  374. register struct ax25 *hdr;
  375. register char *hwaddr;
  376. struct ax25_addr *source;
  377. {
  378.     extern struct ax25_addr mycall;
  379.     register struct ax25_addr *axp;
  380.  
  381.     hwaddr = getaxaddr(&hdr->dest,hwaddr);    /* Destination address */
  382.     ASSIGN(hdr->source,*source);        /* Source address */
  383.     if(hdr->dest.ssid & E){
  384.         /* No digipeaters */
  385.         hdr->ndigis = 0;
  386.         hdr->dest.ssid &= ~E;
  387.         hdr->source.ssid |= E;
  388.         return 2;
  389.     }
  390.     hdr->source.ssid &= ~E;
  391.     hdr->dest.ssid &= ~E;
  392.     for(axp = hdr->digis; axp < &hdr->digis[MAXDIGIS]; axp++){
  393.         hwaddr = getaxaddr(axp,hwaddr);
  394.         if(axp->ssid & E){
  395.             hdr->ndigis = axp - hdr->digis + 1;
  396.             return hdr->ndigis;
  397.         }
  398.     }
  399.     return -1;
  400. }
  401. /* Convert a network-format AX.25 header into a host format structure
  402.  * Return -1 if error, number of addresses if OK
  403.  */
  404. int
  405. ntohax25(hdr,bpp)
  406. register struct ax25 *hdr;    /* Output structure */
  407. struct mbuf **bpp;
  408. {
  409.     register struct ax25_addr *axp;
  410.     char *getaxaddr();
  411.     char buf[AXALEN];
  412.  
  413.     if(pullup(bpp,buf,AXALEN) < AXALEN)
  414.         return -1;
  415.     getaxaddr(&hdr->dest,buf);
  416.  
  417.     if(pullup(bpp,buf,AXALEN) < AXALEN)
  418.         return -1;
  419.     getaxaddr(&hdr->source,buf);
  420.  
  421.     /* Process C bits to get command/response indication */
  422.     if((hdr->source.ssid & C) == (hdr->dest.ssid & C))
  423.         hdr->cmdrsp = UNKNOWN;
  424.     else if(hdr->source.ssid & C)
  425.         hdr->cmdrsp = RESPONSE;
  426.     else
  427.         hdr->cmdrsp = COMMAND;
  428.  
  429.     hdr->ndigis = 0;
  430.     if(hdr->source.ssid & E)
  431.         return 2;    /* No digis */
  432.  
  433.     /* Process digipeaters */
  434.     for(axp = hdr->digis;axp < &hdr->digis[MAXDIGIS]; axp++){
  435.         if(pullup(bpp,buf,AXALEN) < AXALEN)
  436.             return -1;
  437.         getaxaddr(axp,buf);
  438.         if(axp->ssid & E){    /* Last one */
  439.             hdr->ndigis = axp - hdr->digis + 1;
  440.             return hdr->ndigis + 2;            
  441.         }
  442.     }
  443.     return -1;    /* Too many digis */
  444. }
  445.  
  446. /* Figure out the frame type from the control field
  447.  * This is done by masking out any sequence numbers and the
  448.  * poll/final bit after determining the general class (I/S/U) of the frame
  449.  */
  450. int16
  451. ftype(control)
  452. register char control;
  453. {
  454.     if((control & 1) == 0)    /* An I-frame is an I-frame... */
  455.         return I;
  456.     if(control & 2)        /* U-frames use all except P/F bit for type */
  457.         return(control & ~PF & 0xff);
  458.     else            /* S-frames use low order 4 bits for type */
  459.         return(control & 0xf);
  460. }
  461.  
  462. #ifdef NRS
  463. /* Functions for level 3 net/rom support */
  464.  
  465. /* Convert a net/rom network header to host format structure
  466.  * Return -1 if error, 0 if OK
  467.  */
  468.  
  469. int
  470. ntohnr3(hdr,bpp)
  471. register struct nr3hdr *hdr ;    /* output structure */
  472. struct mbuf **bpp ;
  473. {
  474.     register struct ax25_addr *axp ;
  475.     char *getaxaddr() ;
  476.     char buf[AXALEN] ;
  477.  
  478.     if (pullup(bpp,buf,AXALEN) < AXALEN)
  479.         return -1 ;
  480.     getaxaddr(&hdr->source,buf) ;
  481.  
  482.     if (pullup(bpp,buf,AXALEN) < AXALEN)
  483.         return -1 ;
  484.     getaxaddr(&hdr->dest,buf) ;
  485.  
  486.     if (pullup(bpp,&hdr->ttl,1) != 1)
  487.         return -1 ;
  488.  
  489.     return 0 ;
  490. }
  491.  
  492. /* Convert a host-format net/rom level 3 header into an mbuf ready
  493.  * for transmission.
  494.  */
  495.  
  496. struct mbuf *
  497. htonnr3(hdr)
  498. register struct nr3hdr *hdr;
  499. {
  500.     struct mbuf *rbuf ;
  501.     register char *cp ;
  502.  
  503.     if (hdr == (struct nr3hdr *) 0)
  504.         return NULLBUF ;
  505.  
  506.     /* Allocate space for return buffer */
  507.     if ((rbuf = alloc_mbuf(NR3HLEN)) == NULLBUF)
  508.         return NULLBUF ;
  509.  
  510.     rbuf->cnt = NR3HLEN ;
  511.  
  512.     /* Now convert */
  513.     cp = rbuf->data ;
  514.  
  515.     hdr->source.ssid &= ~E ;    /* source E-bit is always off */
  516.     hdr->dest.ssid |= E ;        /* destination E-bit always set */
  517.  
  518.     cp = putaxaddr(cp,&hdr->source) ;
  519.     cp = putaxaddr(cp,&hdr->dest) ;
  520.     *cp = hdr->ttl ;
  521.  
  522.     return rbuf ;
  523. }
  524.  
  525. /* Convert a net/rom routing broadcast destination subpacket from
  526.  * network format to a host format structure.  Return -1 if error,
  527.  * 0 if OK.
  528.  */
  529. int ntohnrdest(ds,bpp)
  530. register struct nr3dest *ds ;
  531. struct mbuf **bpp ;
  532. {
  533.     char buf[AXALEN] ;
  534.     char quality ;
  535.  
  536.     /* get destination callsign */
  537.     if (pullup(bpp,buf,AXALEN) < AXALEN)
  538.         return -1 ;
  539.     memcpy(ds->dest.call,buf,ALEN) ;
  540.     ds->dest.ssid = buf[ALEN] ;
  541.  
  542.     /* get destination alias */
  543.     if (pullup(bpp,ds->alias,ALEN) < ALEN)
  544.         return -1 ;
  545.     ds->alias[ALEN] = '\0' ;
  546.  
  547.     /* get best neighbor callsign */
  548.     if (pullup(bpp,buf,AXALEN) < AXALEN)
  549.         return -1 ;
  550.     memcpy(ds->neighbor.call,buf,ALEN) ;
  551.     ds->neighbor.ssid = buf[ALEN] ;
  552.  
  553.     /* get route quality */
  554.     if (pullup(bpp,&quality,1) < 1)
  555.         return -1 ;
  556.     ds->quality = quality & 0xff ;        /* DG2KK: was uchar() */
  557.  
  558.     return 0 ;
  559. }
  560.  
  561. /* Convert a host-format net/rom destination subpacket into an
  562.  * mbuf ready for transmission as part of a route broadcast
  563.  * packet.
  564.  *
  565.    --- Data is garbled and lost at this point --- hyc
  566.     *cp++ = ds->neighbor.ssid ;
  567.  
  568.     *cp = ds->quality & 0xff ;    /* DG2KK: was uchar() */
  569.  
  570.     return rbuf ;
  571. }
  572. #endif    /* NRS */
  573.