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

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