home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR3 / KA9Q212.ZIP / AX25.C < prev    next >
C/C++ Source or Header  |  1993-07-16  |  13KB  |  469 lines

  1. /* Low level AX.25 code:
  2.  *  incoming frame processing (including digipeating)
  3.  *  IP encapsulation
  4.  *  digipeater routing
  5.  *
  6.  * Copyright 1991 Phil Karn, KA9Q
  7.  */
  8.  
  9. /****************************************************************************
  10. *    $Id: ax25.c 1.2 93/07/16 11:42:19 ROOT_DOS Exp $
  11. *    15 Jul 93    1.2        GT    AX25 conditional.                                *
  12. ****************************************************************************/
  13.  
  14. #include <stdio.h>
  15. #include "global.h"
  16. #include "mbuf.h"
  17. #include "iface.h"
  18. #include "arp.h"
  19. #include "slip.h"
  20. #include "ax25.h"
  21. #include "lapb.h"
  22. #include "netrom.h"
  23. #include "ip.h"
  24. #include "devparam.h"
  25. #include <ctype.h>
  26. #include "config.h"
  27.  
  28. #if    AX25
  29.  
  30. static int axsend __ARGS((struct iface *iface,char *dest,char *source,
  31.     int cmdrsp,int ctl,struct mbuf *data));
  32.  
  33. /* List of AX.25 multicast addresses in network format (shifted ascii).
  34.  * Only the first entry is used for transmission, but an incoming
  35.  * packet with any one of these destination addresses is recognized
  36.  * as a multicast.
  37.  */
  38. char Ax25multi[][AXALEN] = {
  39.     'Q'<<1, 'S'<<1, 'T'<<1, ' '<<1, ' '<<1, ' '<<1, '0'<<1,    /* QST */
  40.     'M'<<1, 'A'<<1, 'I'<<1, 'L'<<1, ' '<<1, ' '<<1, '0'<<1,    /* MAIL */
  41.     'N'<<1, 'O'<<1, 'D'<<1, 'E'<<1, 'S'<<1, ' '<<1, '0'<<1,    /* NODES */
  42.     'I'<<1, 'D'<<1, ' '<<1, ' '<<1, ' '<<1, ' '<<1, '0'<<1,    /* ID */
  43.     'O'<<1, 'P'<<1, 'E'<<1, 'N'<<1, ' '<<1, ' '<<1, '0'<<1,    /* OPEN */
  44.     'C'<<1, 'Q'<<1, ' '<<1, ' '<<1, ' '<<1, ' '<<1, '0'<<1,    /* CQ */
  45.     'B'<<1, 'E'<<1, 'A'<<1, 'C'<<1, 'O'<<1, 'N'<<1, '0'<<1,    /* BEACON */
  46.     'R'<<1, 'M'<<1, 'N'<<1, 'C'<<1, ' '<<1, ' '<<1, '0'<<1,    /* RMNC */
  47.     'A'<<1, 'L'<<1, 'L'<<1, ' '<<1, ' '<<1, ' '<<1, '0'<<1,    /* ALL */
  48.     '\0',
  49. };
  50. char Mycall[AXALEN];
  51. struct ax_route *Ax_routes;    /* Routing table header */
  52. int Digipeat = 1;    /* Controls digipeating */
  53.  
  54. /* Send IP datagrams across an AX.25 link */
  55. int
  56. ax_send(bp,iface,gateway,prec,del,tput,rel)
  57. struct mbuf *bp;
  58. struct iface *iface;
  59. int32 gateway;
  60. int prec;
  61. int del;
  62. int tput;
  63. int rel;
  64. {
  65.     char *hw_addr;
  66.     struct ax25_cb *axp;
  67.     struct mbuf *tbp;
  68.  
  69.     if((hw_addr = res_arp(iface,ARP_AX25,gateway,bp)) == NULLCHAR)
  70.         return 0;    /* Wait for address resolution */
  71.  
  72.     /* UI frames are used for any one of the following three conditions:
  73.      * 1. The "low delay" bit is set in the type-of-service field.
  74.      * 2. The "reliability" TOS bit is NOT set and the interface is in
  75.      *    datagram mode.
  76.      * 3. The destination is the broadcast address (this is helpful
  77.      *    when broadcasting on an interface that's in connected mode).
  78.      */
  79.     if(del || (!rel && (iface->flags == DATAGRAM_MODE))
  80.      || addreq(hw_addr,Ax25multi[0])){
  81.         /* Use UI frame */
  82.         return (*iface->output)(iface,hw_addr,iface->hwaddr,PID_IP,bp);
  83.     }
  84.     /* Reliability is needed; use I-frames in AX.25 connection */
  85.     if((axp = find_ax25(hw_addr)) == NULLAX25){
  86.         /* Open a new connection */
  87.         axp = open_ax25(iface,iface->hwaddr,hw_addr,
  88.          AX_ACTIVE,Axwindow,s_arcall,s_atcall,s_ascall,-1);
  89.         if(axp == NULLAX25){
  90.             free_p(bp);
  91.             return -1;
  92.         }
  93.     }
  94.     if(axp->state == LAPB_DISCONNECTED){
  95.         est_link(axp);
  96.         lapbstate(axp,LAPB_SETUP);
  97.     }
  98.     /* Insert the PID */
  99.     if((tbp = pushdown(bp,1)) == NULLBUF){
  100.         free_p(bp);
  101.         return -1;
  102.     }
  103.     bp = tbp;
  104.     bp->data[0] = PID_IP;
  105.     if((tbp = segmenter(bp,axp->paclen)) == NULLBUF){
  106.         free_p(bp);
  107.         return -1;
  108.     }
  109.     return send_ax25(axp,tbp,-1);
  110. }
  111. /* Add header and send connectionless (UI) AX.25 packet.
  112.  * Note that the calling order here must match enet_output
  113.  * since ARP also uses it.
  114.  */
  115. int
  116. ax_output(iface,dest,source,pid,data)
  117. struct iface *iface;    /* Interface to use; overrides routing table */
  118. char *dest;        /* Destination AX.25 address (7 bytes, shifted) */
  119. char *source;        /* Source AX.25 address (7 bytes, shifted) */
  120. int16 pid;        /* Protocol ID */
  121. struct mbuf *data;    /* Data field (follows PID) */
  122. {
  123.     struct mbuf *bp;
  124.  
  125.     /* Prepend pid to data */
  126.     bp = pushdown(data,1);
  127.     if(bp == NULLBUF){
  128.         free_p(data);
  129.         return -1;
  130.     }
  131.     bp->data[0] = (char)pid;
  132.     return axsend(iface,dest,source,LAPB_COMMAND,UI,bp);
  133. }
  134. /* Common subroutine for sendframe() and ax_output() */
  135. static int
  136. axsend(iface,dest,source,cmdrsp,ctl,data)
  137. struct iface *iface;    /* Interface to use; overrides routing table */
  138. char *dest;        /* Destination AX.25 address (7 bytes, shifted) */
  139. char *source;        /* Source AX.25 address (7 bytes, shifted) */
  140. int cmdrsp;        /* Command/response indication */
  141. int ctl;        /* Control field */
  142. struct mbuf *data;    /* Data field (includes PID) */
  143. {
  144.     struct mbuf *cbp;
  145.     struct ax25 addr;
  146.     struct ax_route *axr;
  147.     char *idest;
  148.     int rval;
  149.  
  150.     /* If the source addr is unspecified, use the interface address */
  151.     if(source[0] == '\0')
  152.         source = iface->hwaddr;
  153.  
  154.     /* If there's a digipeater route, get it */
  155.     axr = ax_lookup(dest);
  156.  
  157.     memcpy(addr.dest,dest,AXALEN);
  158.     memcpy(addr.source,source,AXALEN);
  159.     addr.cmdrsp = cmdrsp;
  160.  
  161.     if(axr != NULLAXR){
  162.         memcpy(addr.digis,axr->digis,axr->ndigis*AXALEN);
  163.         addr.ndigis = axr->ndigis;
  164.         idest = addr.digis[0];
  165.     } else {
  166.         addr.ndigis = 0;
  167.         idest = dest;
  168.     }
  169.     addr.nextdigi = 0;
  170.  
  171.     /* Allocate mbuf for control field, and fill in */
  172.     if((cbp = pushdown(data,1)) == NULLBUF){
  173.         free_p(data);
  174.         return -1;
  175.     }
  176.     cbp->data[0] = ctl;
  177.  
  178.     if((data = htonax25(&addr,cbp)) == NULLBUF){
  179.         free_p(cbp);    /* Also frees data */
  180.         return -1;
  181.     }
  182.     /* This shouldn't be necessary because redirection has already been
  183.      * done at the IP router layer, but just to be safe...
  184.      */
  185.     if(iface->forw != NULLIF){
  186.         logsrc(iface->forw,iface->forw->hwaddr);
  187.         logdest(iface->forw,idest);
  188.         rval = (*iface->forw->raw)(iface->forw,data);
  189.     } else {
  190.         logsrc(iface,iface->hwaddr);
  191.         logdest(iface,idest);
  192.         rval = (*iface->raw)(iface,data);
  193.     }
  194.     return rval;
  195. }
  196. /* Process incoming AX.25 packets.
  197.  * After optional tracing, the address field is examined. If it is
  198.  * directed to us as a digipeater, repeat it.  If it is addressed to
  199.  * us or to QST-0, kick it upstairs depending on the protocol ID.
  200.  */
  201. void
  202. ax_recv(iface,bp)
  203. struct iface *iface;
  204. struct mbuf *bp;
  205. {
  206.     struct mbuf *hbp;
  207.     char control;
  208.     struct ax25 hdr;
  209.     struct ax25_cb *axp;
  210.     struct ax_route *axr;
  211.     char (*mpp)[AXALEN];
  212.     int mcast;
  213.     char *isrc,*idest;    /* "immediate" source and destination */
  214.  
  215.     /* Pull header off packet and convert to host structure */
  216.     if(ntohax25(&hdr,&bp) < 0){
  217.         /* Something wrong with the header */
  218.         free_p(bp);
  219.         return;
  220.     }
  221.     /* If there were digis in this packet and at least one has
  222.      * been passed, then the last passed digi is the immediate source.
  223.      * Otherwise it is the original source.
  224.      */
  225.     if(hdr.ndigis != 0 && hdr.nextdigi != 0)
  226.         isrc = hdr.digis[hdr.nextdigi-1];
  227.     else
  228.         isrc = hdr.source;
  229.  
  230.     /* If there are digis in this packet and not all have been passed,
  231.      * then the immediate destination is the next digi. Otherwise it
  232.      * is the final destination.
  233.      */
  234.     if(hdr.ndigis != 0 && hdr.nextdigi != hdr.ndigis)
  235.         idest = hdr.digis[hdr.nextdigi];
  236.     else
  237.         idest = hdr.dest;
  238.  
  239.     /* Don't log our own packets if we overhear them, as they're
  240.      * already logged by axsend() and by the digipeater code.
  241.      */
  242.     if(!addreq(isrc,iface->hwaddr)){
  243.         logsrc(iface,isrc);
  244.         logdest(iface,idest);
  245.     }
  246.     /* Examine immediate destination for a multicast address */
  247.     mcast = 0;
  248.     for(mpp = Ax25multi;(*mpp)[0] != '\0';mpp++){
  249.         if(addreq(idest,*mpp)){
  250.             mcast = 1;
  251.             break;
  252.         }
  253.     }
  254.     if(!mcast && !addreq(idest,iface->hwaddr)){
  255.         /* Not a broadcast, and not addressed to us. Inhibit
  256.          * transmitter to avoid colliding with addressed station's
  257.          * response, and discard packet.
  258.          */
  259.         if(iface->ioctl != NULL)
  260.             (*iface->ioctl)(iface,PARAM_MUTE,1,-1);
  261.         free_p(bp);
  262.         return;
  263.     }
  264.     if(!mcast && iface->ioctl != NULL){
  265.         /* Packet was sent to us; abort transmit inhibit */
  266.         (*iface->ioctl)(iface,PARAM_MUTE,1,0);
  267.     }
  268.     /* At this point, packet is either addressed to us, or is
  269.      * a multicast.
  270.      */
  271.     if(hdr.nextdigi < hdr.ndigis){
  272.         /* Packet requests digipeating. See if we can repeat it. */
  273.         if(Digipeat && !mcast){
  274.             /* Yes, kick it back out. htonax25 will set the
  275.              * repeated bit.
  276.              */
  277.             hdr.nextdigi++;
  278.             if((hbp = htonax25(&hdr,bp)) != NULLBUF){
  279.                 if(iface->forw != NULLIF){
  280.                     logsrc(iface->forw,iface->forw->hwaddr);
  281.                     logdest(iface->forw,hdr.digis[hdr.nextdigi]);
  282.                     (*iface->forw->raw)(iface->forw,hbp);
  283.                 } else {
  284.                     logsrc(iface,iface->hwaddr);
  285.                     logdest(iface,hdr.digis[hdr.nextdigi]);
  286.                     (*iface->raw)(iface,hbp);
  287.                 }
  288.                 bp = NULLBUF;
  289.             }
  290.         }
  291.         free_p(bp);    /* Dispose if not forwarded */
  292.         return;
  293.     }
  294.     /* If we reach this point, then the packet has passed all digis,
  295.      * and is either addressed to us or is a multicast.
  296.      */
  297.     if(bp == NULLBUF)
  298.         return;        /* Nothing left */
  299.  
  300.     /* If there's no locally-set entry in the routing table and
  301.      * this packet has digipeaters, create or update it. Leave
  302.      * local routes alone.
  303.      */
  304.     if(((axr = ax_lookup(hdr.source)) == NULLAXR || axr->type == AX_AUTO)
  305.      && hdr.ndigis > 0){
  306.         char digis[MAXDIGIS][AXALEN];
  307.         int i,j;
  308.  
  309.         /* Construct reverse digipeater path */
  310.         for(i=hdr.ndigis-1,j=0;i >= 0;i--,j++){
  311.             memcpy(digis[j],hdr.digis[i],AXALEN);
  312.             digis[j][ALEN] &= ~(E|REPEATED);
  313.         }
  314.         ax_add(hdr.source,AX_AUTO,digis,hdr.ndigis);
  315.     }
  316.     /* Sneak a peek at the control field. This kludge is necessary because
  317.      * AX.25 lacks a proper protocol ID field between the address and LAPB
  318.      * sublayers; a control value of UI indicates that LAPB is to be
  319.      * bypassed.
  320.      */
  321.     control = *bp->data & ~PF;
  322.  
  323.     if(uchar(control) == UI){
  324.         int pid;
  325.         struct axlink *ipp;
  326.  
  327.         (void) PULLCHAR(&bp);
  328.         if((pid = PULLCHAR(&bp)) == -1)
  329.             return;        /* No PID */
  330.         /* Find network level protocol and hand it off */
  331.         for(ipp = Axlink;ipp->funct != NULL;ipp++){
  332.             if(ipp->pid == pid)
  333.                 break;
  334.         }
  335.         if(ipp->funct != NULL)
  336.             (*ipp->funct)(iface,NULLAX25,hdr.source,hdr.dest,bp,mcast);
  337.         else
  338.             free_p(bp);
  339.         return;
  340.     }
  341.     /* Everything from here down is connected-mode LAPB, so ignore
  342.      * multicasts
  343.      */
  344.     if(mcast){
  345.         free_p(bp);
  346.         return;
  347.     }
  348.     /* Find the source address in hash table */
  349.     if((axp = find_ax25(hdr.source)) == NULLAX25){
  350.         /* Create a new ax25 entry for this guy,
  351.          * insert into hash table keyed on his address,
  352.          * and initialize table entries
  353.          */
  354.         if((axp = cr_ax25(hdr.source)) == NULLAX25){
  355.             free_p(bp);
  356.             return;
  357.         }
  358.         /* Swap source and destination */
  359.         memcpy(axp->remote,hdr.source,AXALEN);
  360.         memcpy(axp->local,hdr.dest,AXALEN);
  361.         axp->iface = iface;
  362.     }
  363.     if(hdr.cmdrsp == LAPB_UNKNOWN)
  364.         axp->proto = V1;    /* Old protocol in use */
  365.  
  366.     lapb_input(axp,hdr.cmdrsp,bp);
  367. }
  368. /* General purpose AX.25 frame output */
  369. int
  370. sendframe(axp,cmdrsp,ctl,data)
  371. struct ax25_cb *axp;
  372. int cmdrsp;
  373. int ctl;
  374. struct mbuf *data;
  375. {
  376.     return axsend(axp->iface,axp->remote,axp->local,cmdrsp,ctl,data);
  377. }
  378. /* Find a route for an AX.25 address */
  379. struct ax_route *
  380. ax_lookup(target)
  381. char *target;
  382. {
  383.     register struct ax_route *axr;
  384.     struct ax_route *axlast = NULLAXR;
  385.  
  386.     for(axr = Ax_routes; axr != NULLAXR; axlast=axr,axr = axr->next){
  387.         if(addreq(axr->target,target)){
  388.             if(axr != Ax_routes){
  389.                 /* Move entry to top of list to speed
  390.                  * future searches
  391.                  */
  392.                 axlast->next = axr->next;
  393.                 axr->next = Ax_routes;
  394.                 Ax_routes = axr;
  395.  
  396.             }
  397.             return axr;
  398.         }
  399.     }
  400.     return axr;
  401. }
  402. /* Add an entry to the AX.25 routing table */
  403. struct ax_route *
  404. ax_add(target,type,digis,ndigis)
  405. char *target;
  406. int type;
  407. char digis[][AXALEN];
  408. int ndigis;
  409. {
  410.     register struct ax_route *axr;
  411.  
  412.     if(ndigis < 0 || ndigis > MAXDIGIS)
  413.         return NULLAXR;
  414.  
  415.     if((axr = ax_lookup(target)) == NULLAXR){
  416.         axr = (struct ax_route *)callocw(1,sizeof(struct ax_route));
  417.         axr->next = Ax_routes;
  418.         Ax_routes = axr;
  419.         memcpy(axr->target,target,AXALEN);
  420.         axr->ndigis = ndigis;
  421.     }
  422.     axr->type = type;
  423.     if(axr->ndigis != ndigis)
  424.         axr->ndigis = ndigis;
  425.  
  426.     memcpy(axr->digis,digis[0],ndigis*AXALEN);
  427.     return axr;
  428. }
  429. int
  430. ax_drop(target)
  431. char *target;
  432. {
  433.     register struct ax_route *axr;
  434.     struct ax_route *axlast = NULLAXR;
  435.  
  436.     for(axr = Ax_routes;axr != NULLAXR;axlast=axr,axr=axr->next)
  437.         if(memcmp(axr->target,target,AXALEN) == 0)
  438.             break;
  439.     if(axr == NULLAXR)
  440.         return -1;    /* Not in table! */
  441.     if(axlast != NULLAXR)
  442.         axlast->next = axr->next;
  443.     else
  444.         Ax_routes = axr->next;
  445.     
  446.     free((char *)axr);
  447.     return 0;
  448. }
  449. /* Handle ordinary incoming data (no network protocol) */
  450. void
  451. axnl3(iface,axp,src,dest,bp,mcast)
  452. struct iface *iface;
  453. struct ax25_cb *axp;
  454. char *src;
  455. char *dest;
  456. struct mbuf *bp;
  457. int mcast;
  458. {
  459.     if(axp == NULLAX25){
  460.         beac_input(iface,src,bp);
  461.     } else {
  462.         append(&axp->rxq,bp);
  463.         if(axp->r_upcall != NULLVFP)
  464.             (*axp->r_upcall)(axp,len_p(axp->rxq));
  465.     }
  466. }
  467.  
  468. #endif    AX25
  469.