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