home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 3 / hamradioversion3.0examsandprograms1992.iso / packet / n17jsrc / lapb.c < prev    next >
C/C++ Source or Header  |  1991-04-18  |  18KB  |  705 lines

  1. /* Link Access Procedures Balanced (LAPB), the upper sublayer of
  2.  * AX.25 Level 2.
  3.  * Copyright 1991 Phil Karn, KA9Q
  4.  */
  5. #include "global.h"
  6. #include "mbuf.h"
  7. #include "timer.h"
  8. #include "ax25.h"
  9. #include "lapb.h"
  10. #include "ip.h"
  11. #include "netrom.h"
  12.  
  13. static void handleit __ARGS((struct ax25_cb *axp,int pid,struct mbuf *bp));
  14. static void procdata __ARGS((struct ax25_cb *axp,struct mbuf *bp));
  15. static int ackours __ARGS((struct ax25_cb *axp,int16 n));
  16. static void clr_ex __ARGS((struct ax25_cb *axp));
  17. static void enq_resp __ARGS((struct ax25_cb *axp));
  18. static void inv_rex __ARGS((struct ax25_cb *axp));
  19.  
  20. /* Process incoming frames */
  21. int
  22. lapb_input(axp,cmdrsp,bp)
  23. struct ax25_cb *axp;        /* Link control structure */
  24. int cmdrsp;            /* Command/response flag */
  25. struct mbuf *bp;        /* Rest of frame, starting with ctl */
  26. {
  27.     int control;
  28.     int class;        /* General class (I/S/U) of frame */
  29.     int16 type;        /* Specific type (I/RR/RNR/etc) of frame */
  30.     char pf;        /* extracted poll/final bit */
  31.     char poll = 0;
  32.     char final = 0;
  33.     int16 nr;        /* ACK number of incoming frame */
  34.     int16 ns;        /* Seq number of incoming frame */
  35.     int16 tmp;
  36.  
  37.     if(bp == NULLBUF || axp == NULLAX25){
  38.         free_p(bp);
  39.         return -1;
  40.     }
  41.  
  42.     /* Extract the various parts of the control field for easy use */
  43.     if((control = PULLCHAR(&bp)) == -1){
  44.         free_p(bp);    /* Probably not necessary */
  45.         return -1;
  46.     }
  47.     type = ftype(control);
  48.     class = type & 0x3;
  49.     pf = control & PF;
  50.     /* Check for polls and finals */
  51.     if(pf){
  52.         switch(cmdrsp){
  53.         case LAPB_COMMAND:
  54.             poll = YES;
  55.             break;
  56.         case LAPB_RESPONSE:
  57.             final = YES;
  58.             break;
  59.         }
  60.     }
  61.     /* Extract sequence numbers, if present */
  62.     switch(class){
  63.     case I:
  64.     case I+2:
  65.         ns = (control >> 1) & MMASK;
  66.     case S:    /* Note fall-thru */
  67.         nr = (control >> 5) & MMASK;
  68.         break;
  69.     }
  70.     /* This section follows the SDL diagrams by K3NA fairly closely */
  71.     switch(axp->state){
  72.     case LAPB_DISCONNECTED:
  73.         switch(type){
  74.         case SABM:    /* Initialize or reset link */
  75.             sendctl(axp,LAPB_RESPONSE,UA|pf);    /* Always accept */
  76.             clr_ex(axp);
  77.             axp->unack = axp->vr = axp->vs = 0;
  78.             lapbstate(axp,LAPB_CONNECTED);/* Resets state counters */
  79.             axp->srt = Axirtt;
  80.             axp->mdev = 0;
  81.             set_timer(&axp->t1,2*axp->srt);
  82.             start_timer(&axp->t3);
  83.             start_timer(&axp->t4);
  84.             break;
  85.         case DISC:    /* Always answer a DISC with a DM */
  86.             sendctl(axp,LAPB_RESPONSE,DM|pf);
  87.             break;
  88.         case DM:    /* Ignore to avoid infinite loops */
  89.             break;
  90.         default:    /* All others get DM */
  91.             if(poll)
  92.                 sendctl(axp,LAPB_RESPONSE,DM|pf);
  93.             break;
  94.         }
  95.         if(axp->state == LAPB_DISCONNECTED){    /* we can close connection */
  96.             stop_timer(&axp->t1);    /* waste all the timers */
  97.             stop_timer(&axp->t3);
  98.             stop_timer(&axp->t4);
  99.             free_q(&axp->txq);    /* lose transmit queue */
  100.             del_ax25(axp);        /* clean out the trash */
  101.         }
  102.         break;
  103.     case LAPB_SETUP:
  104.         switch(type){
  105.         case SABM:    /* Simultaneous open */
  106.             sendctl(axp,LAPB_RESPONSE,UA|pf);
  107.             break;
  108.         case DISC:
  109.             sendctl(axp,LAPB_RESPONSE,DM|pf);
  110.             nr_derate(axp);
  111.             free_q(&axp->txq);
  112.             stop_timer(&axp->t1);
  113.             axp->reason = LB_DM;
  114.             lapbstate(axp,LAPB_DISCONNECTED);
  115.             break;
  116.         case UA:    /* Connection accepted */
  117.             /* Note: xmit queue not cleared */
  118.             stop_timer(&axp->t1);
  119.             start_timer(&axp->t3);
  120.             axp->unack = axp->vr = axp->vs = 0;
  121.             lapbstate(axp,LAPB_CONNECTED);
  122.             start_timer(&axp->t4);
  123.             break;
  124.         case DM:    /* Connection refused */
  125.             free_q(&axp->txq);
  126.             stop_timer(&axp->t1);
  127.             axp->reason = LB_DM;
  128.             lapbstate(axp,LAPB_DISCONNECTED);
  129.             break;
  130.         default:    /* Respond with DM only to command polls */
  131.             if(poll)
  132.                 sendctl(axp,LAPB_RESPONSE,DM|pf);
  133.             break;
  134.         }
  135.         break;
  136.     case LAPB_DISCPENDING:
  137.         switch(type){
  138.         case SABM:
  139.             sendctl(axp,LAPB_RESPONSE,DM|pf);
  140.             break;
  141.         case DISC:
  142.             sendctl(axp,LAPB_RESPONSE,UA|pf);
  143.             break;
  144.         case UA:
  145.         case DM:
  146.             stop_timer(&axp->t1);
  147.             lapbstate(axp,LAPB_DISCONNECTED);
  148.             break;
  149.         default:    /* Respond with DM only to command polls */
  150.             if(poll)
  151.                 sendctl(axp,LAPB_RESPONSE,DM|pf);
  152.             break;
  153.         }
  154.         break;
  155.     case LAPB_CONNECTED:
  156.         switch(type){
  157.         case SABM:
  158.             sendctl(axp,LAPB_RESPONSE,UA|pf);
  159.             clr_ex(axp);
  160.             free_q(&axp->txq);
  161.             stop_timer(&axp->t1);
  162.             start_timer(&axp->t3);
  163.             axp->unack = axp->vr = axp->vs = 0;
  164.             lapbstate(axp,LAPB_CONNECTED); /* Purge queues */
  165.             break;
  166.         case DISC:
  167.             free_q(&axp->txq);
  168.             sendctl(axp,LAPB_RESPONSE,UA|pf);
  169.             stop_timer(&axp->t1);
  170.             stop_timer(&axp->t3);
  171.             axp->reason = LB_NORMAL;
  172.             lapbstate(axp,LAPB_DISCONNECTED);
  173.             break;
  174.         case DM:
  175.             axp->reason = LB_DM;
  176.             lapbstate(axp,LAPB_DISCONNECTED);
  177.             break;
  178.         case UA:
  179.             est_link(axp);
  180.             lapbstate(axp,LAPB_SETUP);    /* Re-establish */    
  181.             break;            
  182.         case FRMR:
  183.             est_link(axp);
  184.             lapbstate(axp,LAPB_SETUP);    /* Re-establish link */
  185.             break;
  186.         case RR:
  187.         case RNR:
  188.             axp->flags.remotebusy = (control == RNR) ? YES : NO;
  189.             if(poll)
  190.                 enq_resp(axp);
  191.             ackours(axp,nr);
  192.             break;
  193.         case REJ:
  194.             axp->flags.remotebusy = NO;
  195.             if(poll)
  196.                 enq_resp(axp);
  197.             ackours(axp,nr);
  198.             stop_timer(&axp->t1);
  199.             start_timer(&axp->t3);
  200.             /* This may or may not actually invoke transmission,
  201.              * depending on whether this REJ was caused by
  202.              * our losing his prior ACK.
  203.              */
  204.             inv_rex(axp);
  205.             break;    
  206.         case I:
  207.             ackours(axp,nr); /** == -1) */
  208.             start_timer(&axp->t4);
  209.             if(len_p(axp->rxq) >= axp->window){
  210.                 /* Too bad he didn't listen to us; he'll
  211.                  * have to resend the frame later. This
  212.                  * drastic action is necessary to avoid
  213.                  * deadlock.
  214.                  */
  215.                 if(poll)
  216.                     sendctl(axp,LAPB_RESPONSE,RNR|pf);
  217.                 free_p(bp);
  218.                 bp = NULLBUF;
  219.                 break;
  220.             }
  221.             /* Reject or ignore I-frames with receive sequence number errors */
  222.             if(ns != axp->vr){
  223.                 if(axp->proto == V1 || !axp->flags.rejsent){
  224.                     axp->flags.rejsent = YES;
  225.                     sendctl(axp,LAPB_RESPONSE,REJ | pf);
  226.                 } else if(poll)
  227.                     enq_resp(axp);
  228.                 axp->response = 0;
  229.                 break;
  230.             }
  231.             axp->flags.rejsent = NO;
  232.             axp->vr = (axp->vr+1) & MMASK;
  233.             tmp = len_p(axp->rxq) >= axp->window ? RNR : RR;
  234.             if(poll){
  235.                 sendctl(axp,LAPB_RESPONSE,tmp|PF);
  236.             } else {
  237.                 axp->response = tmp;
  238.             }
  239.             procdata(axp,bp);
  240.             bp = NULLBUF;
  241.             break;
  242.         default:    /* All others ignored */
  243.             break;
  244.         }
  245.         break;
  246.     case LAPB_RECOVERY:
  247.         switch(type){
  248.         case SABM:
  249.             sendctl(axp,LAPB_RESPONSE,UA|pf);
  250.             clr_ex(axp);
  251.             stop_timer(&axp->t1);
  252.             start_timer(&axp->t3);
  253.             axp->unack = axp->vr = axp->vs = 0;
  254.             lapbstate(axp,LAPB_CONNECTED); /* Purge queues */
  255.             if(!run_timer(&axp->t4))
  256.                 start_timer(&axp->t4);
  257.             break;
  258.         case DISC:
  259.             free_q(&axp->txq);
  260.             sendctl(axp,LAPB_RESPONSE,UA|pf);
  261.             stop_timer(&axp->t1);
  262.             stop_timer(&axp->t3);
  263.             axp->response = UA;
  264.             axp->reason = LB_NORMAL;
  265.             lapbstate(axp,LAPB_DISCONNECTED);
  266.             break;
  267.         case DM:
  268.             nr_derate(axp);
  269.             axp->reason = LB_DM;
  270.             lapbstate(axp,LAPB_DISCONNECTED);
  271.             break;
  272.         case UA:
  273.             est_link(axp);
  274.             lapbstate(axp,LAPB_SETUP);    /* Re-establish */    
  275.             break;
  276.         case FRMR:
  277.             est_link(axp);
  278.             lapbstate(axp,LAPB_SETUP);    /* Re-establish link */
  279.             break;
  280.         case RR:
  281.         case RNR:
  282.             axp->flags.remotebusy = (control == RNR) ? YES : NO;
  283.             if(axp->proto == V1 || final){
  284.                 stop_timer(&axp->t1);
  285.                 ackours(axp,nr);
  286.                 if(axp->unack != 0){
  287.                     inv_rex(axp);
  288.                 } else {
  289.                     start_timer(&axp->t3);
  290.                     lapbstate(axp,LAPB_CONNECTED);
  291.                     if(!run_timer(&axp->t4))
  292.                         start_timer(&axp->t4);
  293.                 }
  294.             } else {
  295.                 if(poll)
  296.                     enq_resp(axp);
  297.                 ackours(axp,nr);
  298.                 /* Keep timer running even if all frames
  299.                  * were acked, since we must see a Final
  300.                  */
  301.                 if(!run_timer(&axp->t1))
  302.                     start_timer(&axp->t1);
  303.             }
  304.             break;
  305.         case REJ:
  306.             axp->flags.remotebusy = NO;
  307.             /* Don't insist on a Final response from the old proto */
  308.             if(axp->proto == V1 || final){
  309.                 stop_timer(&axp->t1);
  310.                 ackours(axp,nr);
  311.                 if(axp->unack != 0){
  312.                     inv_rex(axp);
  313.                 } else {
  314.                     start_timer(&axp->t3);
  315.                     lapbstate(axp,LAPB_CONNECTED);
  316.                     if(!run_timer(&axp->t4))
  317.                         start_timer(&axp->t4);
  318.                 }
  319.             } else {
  320.                 if(poll)
  321.                     enq_resp(axp);
  322.                 ackours(axp,nr);
  323.                 if(axp->unack != 0){
  324.                     /* This is certain to trigger output */
  325.                     inv_rex(axp);
  326.                 }
  327.                 /* A REJ that acks everything but doesn't
  328.                  * have the F bit set can cause a deadlock.
  329.                  * So make sure the timer is running.
  330.                  */
  331.                 if(!run_timer(&axp->t1))
  332.                     start_timer(&axp->t1);
  333.             }
  334.             break;
  335.         case I:
  336.             ackours(axp,nr); /** == -1) */
  337.             /* Make sure timer is running, since an I frame
  338.              * cannot satisfy a poll
  339.              */
  340.             if(!run_timer(&axp->t1))
  341.                 start_timer(&axp->t1);
  342.             if(len_p(axp->rxq) >= axp->window){
  343.                 /* Too bad he didn't listen to us; he'll
  344.                  * have to resend the frame later. This
  345.                  * drastic action is necessary to avoid
  346.                  * memory deadlock.
  347.                  */
  348.                 sendctl(axp,LAPB_RESPONSE,RNR | pf);
  349.                 free_p(bp);
  350.                 bp = NULLBUF;
  351.                 break;
  352.             }
  353.             /* Reject or ignore I-frames with receive sequence number errors */
  354.             if(ns != axp->vr){
  355.                 if(axp->proto == V1 || !axp->flags.rejsent){
  356.                     axp->flags.rejsent = YES;
  357.                     sendctl(axp,LAPB_RESPONSE,REJ | pf);
  358.                 } else if(poll)
  359.                     enq_resp(axp);
  360.  
  361.                 axp->response = 0;
  362.                 break;
  363.             }
  364.             axp->flags.rejsent = NO;
  365.             axp->vr = (axp->vr+1) & MMASK;
  366.             tmp = len_p(axp->rxq) >= axp->window ? RNR : RR;
  367.             if(poll){
  368.                 sendctl(axp,LAPB_RESPONSE,tmp|PF);
  369.             } else {
  370.                 axp->response = tmp;
  371.             }
  372.             procdata(axp,bp);
  373.             bp = NULLBUF;
  374.             break;
  375.         default:
  376.             break;        /* Ignored */
  377.         }
  378.         break;
  379.     }
  380.     free_p(bp);    /* In case anything's left */
  381.  
  382.     /* See if we can send some data, perhaps piggybacking an ack.
  383.      * If successful, lapb_output will clear axp->response.
  384.      */
  385.     lapb_output(axp);
  386.     if(axp->response != 0){
  387.         sendctl(axp,LAPB_RESPONSE,axp->response);
  388.         axp->response = 0;
  389.     }
  390.     return 0;
  391. }
  392.  
  393. /* Handle incoming acknowledgements for frames we've sent.
  394.  * Free frames being acknowledged.
  395.  * Return -1 to cause a frame reject if number is bad, 0 otherwise
  396.  */
  397. static int
  398. ackours(axp,n)
  399. struct ax25_cb *axp;
  400. int16 n;
  401. {    
  402.     struct mbuf *bp;
  403.     int acked = 0;    /* Count of frames acked by this ACK */
  404.     int16 oldest;    /* Seq number of oldest unacked I-frame */
  405.     int32 rtt,abserr;
  406.  
  407.     /* Free up acknowledged frames by purging frames from the I-frame
  408.      * transmit queue. Start at the remote end's last reported V(r)
  409.      * and keep going until we reach the new sequence number.
  410.      * If we try to free a null pointer,
  411.      * then we have a frame reject condition.
  412.      */
  413.     oldest = (axp->vs - axp->unack) & MMASK;
  414.     while(axp->unack != 0 && oldest != n){
  415.         if((bp = dequeue(&axp->txq)) == NULLBUF){
  416.             /* Acking unsent frame */
  417.             return -1;
  418.         }
  419.         free_p(bp);
  420.         axp->unack--;
  421.         acked++;
  422.         if(axp->flags.rtt_run && axp->rtt_seq == oldest){
  423.             /* A frame being timed has been acked */
  424.             axp->flags.rtt_run = 0;
  425.             /* Update only if frame wasn't retransmitted */
  426.             if(!axp->flags.retrans){
  427.                 rtt = msclock() - axp->rtt_time;
  428.                 abserr = (rtt > axp->srt) ? rtt - axp->srt :
  429.                  axp->srt - rtt;
  430.  
  431.                 /* Run SRT and mdev integrators */
  432.                 axp->srt = ((axp->srt * 7) + rtt + 4) >> 3;
  433.                 axp->mdev = ((axp->mdev*3) + abserr + 2) >> 2;
  434.                 /* Update timeout */
  435.                 set_timer(&axp->t1,4*axp->mdev+axp->srt);
  436.             }
  437.         }
  438.         axp->flags.retrans = 0;
  439.         axp->retries = 0;
  440.         oldest = (oldest + 1) & MMASK;
  441.     }
  442.     if(axp->unack == 0){
  443.         /* All frames acked, stop timeout */
  444.         stop_timer(&axp->t1);
  445.         start_timer(&axp->t3);
  446.     } else if(acked != 0) { 
  447.         /* Partial ACK; restart timer */
  448.         start_timer(&axp->t1);
  449.     }
  450.     if(acked != 0){
  451.         /* If user has set a transmit upcall, indicate how many frames
  452.          * may be queued
  453.          */
  454.         if(axp->t_upcall != NULLVFP)
  455.             (*axp->t_upcall)(axp,axp->paclen * (axp->maxframe - axp->unack));
  456.     }
  457.     return 0;
  458. }
  459.  
  460. /* Establish data link */
  461. void
  462. est_link(axp)
  463. struct ax25_cb *axp;
  464. {
  465.     clr_ex(axp);
  466.     axp->retries = 0;
  467.     sendctl(axp,LAPB_COMMAND,SABM|PF);
  468.     stop_timer(&axp->t3);
  469.     start_timer(&axp->t1);
  470. }
  471. /* Clear exception conditions */
  472. static void
  473. clr_ex(axp)
  474. struct ax25_cb *axp;
  475. {
  476.     axp->flags.remotebusy = NO;
  477.     axp->flags.rejsent = NO;
  478.     axp->response = 0;
  479.     stop_timer(&axp->t3);
  480. }
  481. /* Enquiry response */
  482. static void
  483. enq_resp(axp)
  484. struct ax25_cb *axp;
  485. {
  486.     char ctl;
  487.  
  488.     ctl = len_p(axp->rxq) >= axp->window ? RNR|PF : RR|PF;    
  489.     sendctl(axp,LAPB_RESPONSE,ctl);
  490.     axp->response = 0;
  491.     stop_timer(&axp->t3);
  492. }
  493. /* Invoke retransmission */
  494. static void
  495. inv_rex(axp)
  496. struct ax25_cb *axp;
  497. {
  498.     axp->vs -= axp->unack;
  499.     axp->vs &= MMASK;
  500.     axp->unack = 0;
  501. }
  502. /* Send S or U frame to currently connected station */
  503. int
  504. sendctl(axp,cmdrsp,cmd)
  505. struct ax25_cb *axp;
  506. int cmdrsp;
  507. int cmd;
  508. {
  509.     if((ftype((char)cmd) & 0x3) == S)    /* Insert V(R) if S frame */
  510.         cmd |= (axp->vr << 5);
  511.     return sendframe(axp,cmdrsp,cmd,NULLBUF);
  512. }
  513. /* Start data transmission on link, if possible
  514.  * Return number of frames sent
  515.  */
  516. int
  517. lapb_output(axp)
  518. register struct ax25_cb *axp;
  519. {
  520.     register struct mbuf *bp;
  521.     struct mbuf *tbp;
  522.     char control;
  523.     int sent = 0;
  524.     int i;
  525.  
  526.     if(axp == NULLAX25
  527.      || (axp->state != LAPB_RECOVERY && axp->state != LAPB_CONNECTED)
  528.      || axp->flags.remotebusy)
  529.         return 0;
  530.  
  531.     /* Dig into the send queue for the first unsent frame */
  532.     bp = axp->txq;
  533.     for(i = 0; i < axp->unack; i++){
  534.         if(bp == NULLBUF)
  535.             break;    /* Nothing to do */
  536.         bp = bp->anext;
  537.     }
  538.     /* Start at first unsent I-frame, stop when either the
  539.      * number of unacknowledged frames reaches the maxframe limit,
  540.      * or when there are no more frames to send
  541.      */
  542.     while(bp != NULLBUF && axp->unack < axp->maxframe){
  543.         control = I | (axp->vs++ << 1) | (axp->vr << 5);
  544.         axp->vs &= MMASK;
  545.         dup_p(&tbp,bp,0,len_p(bp));
  546.         if(tbp == NULLBUF)
  547.             return sent;    /* Probably out of memory */
  548.         sendframe(axp,LAPB_COMMAND,control,tbp);
  549.         start_timer(&axp->t4);
  550.         axp->unack++;
  551.         /* We're implicitly acking any data he's sent, so stop any
  552.          * delayed ack
  553.          */
  554.         axp->response = 0;
  555.         if(!run_timer(&axp->t1)){
  556.             stop_timer(&axp->t3);
  557.             start_timer(&axp->t1);
  558.         }
  559.         sent++;
  560.         bp = bp->anext;
  561.         if(!axp->flags.rtt_run){
  562.             /* Start round trip timer */
  563.             axp->rtt_seq = (control >> 1) & MMASK;
  564.             axp->rtt_time = msclock();
  565.             axp->flags.rtt_run = 1;
  566.         }
  567.     }
  568.     return sent;
  569. }
  570. /* Set new link state */
  571. void
  572. lapbstate(axp,s)
  573. struct ax25_cb *axp;
  574. int s;
  575. {
  576.     int oldstate;
  577.  
  578.     oldstate = axp->state;
  579.     axp->state = s;
  580.     if(s == LAPB_DISCONNECTED){
  581.         stop_timer(&axp->t1);
  582.         stop_timer(&axp->t3);
  583.         stop_timer(&axp->t4);
  584.         free_q(&axp->txq);
  585.     }
  586.     /* Don't bother the client unless the state is really changing */
  587.     if((oldstate != s) && (axp->s_upcall != NULLVFP))
  588.         (*axp->s_upcall)(axp,oldstate,s);
  589. }
  590. /* Process a valid incoming I frame */
  591. static void
  592. procdata(axp,bp)
  593. struct ax25_cb *axp;
  594. struct mbuf *bp;
  595. {
  596.     int pid;
  597.     int seq;
  598.  
  599.     /* Extract level 3 PID */
  600.     if((pid = PULLCHAR(&bp)) == -1)
  601.         return;    /* No PID */
  602.  
  603.     if(axp->segremain != 0){
  604.         /* Reassembly in progress; continue */
  605.         seq = PULLCHAR(&bp);
  606.         if(pid == PID_SEGMENT
  607.          && (seq & SEG_REM) == axp->segremain - 1){
  608.             /* Correct, in-order segment */
  609.             append(&axp->rxasm,bp);
  610.             if((axp->segremain = (seq & SEG_REM)) == 0){
  611.                 /* Done; kick it upstairs */
  612.                 bp = axp->rxasm;
  613.                 axp->rxasm = NULLBUF;
  614.                 pid = PULLCHAR(&bp);
  615.                 handleit(axp,pid,bp);
  616.             }
  617.         } else {
  618.             /* Error! */
  619.             free_p(axp->rxasm);
  620.             axp->rxasm = NULLBUF;
  621.             axp->segremain = 0;
  622.             free_p(bp);
  623.         }
  624.     } else {
  625.         /* No reassembly in progress */
  626.         if(pid == PID_SEGMENT){
  627.             /* Start reassembly */
  628.             seq = PULLCHAR(&bp);
  629.             if(!(seq & SEG_FIRST)){
  630.                 free_p(bp);    /* not first seg - error! */
  631.             } else {
  632.                 /* Put first segment on list */
  633.                 axp->segremain = seq & SEG_REM;
  634.                 axp->rxasm = bp;
  635.             }
  636.         } else {
  637.             /* Normal frame; send upstairs */
  638.             handleit(axp,pid,bp);
  639.         }
  640.     }
  641. }
  642. /* New-style frame segmenter. Returns queue of segmented fragments, or
  643.  * original packet if small enough
  644.  */
  645. struct mbuf *
  646. segmenter(bp,ssize)
  647. struct mbuf *bp;    /* Complete packet */
  648. int16 ssize;        /* Max size of frame segments */
  649. {
  650.     struct mbuf *result = NULLBUF;
  651.     struct mbuf *bptmp,*bp1;
  652.     int16 len,offset;
  653.     int segments;
  654.  
  655.     /* See if packet is too small to segment. Note 1-byte grace factor
  656.      * so the PID will not cause segmentation of a 256-byte IP datagram.
  657.      */
  658.     len = len_p(bp);
  659.     if(len <= ssize+1)
  660.         return bp;    /* Too small to segment */
  661.  
  662.     ssize -= 2;        /* ssize now equal to data portion size */
  663.     segments = 1 + (len - 1) / ssize;    /* # segments  */
  664.     offset = 0;
  665.  
  666.     while(segments != 0){
  667.         offset += dup_p(&bptmp,bp,offset,ssize);
  668.         if(bptmp == NULLBUF){
  669.             free_q(&result);
  670.             break;
  671.         }
  672.         /* Make room for segmentation header */
  673.         if((bp1 = pushdown(bptmp,2)) == NULLBUF){
  674.             free_p(bptmp);
  675.             free_q(&result);
  676.             break;
  677.         }
  678.         bp1->data[0] = PID_SEGMENT;
  679.         bp1->data[1] = --segments;
  680.         if(offset == ssize)
  681.             bp1->data[1] |= SEG_FIRST;
  682.         enqueue(&result,bp1);
  683.     }
  684.     free_p(bp);
  685.     return result;
  686. }
  687.  
  688. static void
  689. handleit(axp,pid,bp)
  690. struct ax25_cb *axp;
  691. int pid;
  692. struct mbuf *bp;
  693. {
  694.     struct axlink *ipp;
  695.  
  696.     for(ipp = Axlink;ipp->funct != NULL;ipp++){
  697.         if(ipp->pid == pid)
  698.             break;
  699.     }
  700.     if(ipp->funct != NULL)
  701.         (*ipp->funct)(axp->iface,axp,NULLCHAR,NULLCHAR,bp,0);
  702.     else
  703.         free_p(bp);
  704. }
  705.