home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / ip / ppp / dp-2.3 / sys / ppp_async.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-07  |  22.3 KB  |  789 lines

  1. /* ppp_async.c - Streams async functions Also does FCS
  2.     Copyright (C) 1990  Brad K. Clements, All Rights Reserved
  3.     fcstab and some ideas nicked from if_ppp.c from cmu. See copyright notice in if_ppp.h
  4.      and Readme.streams
  5. */
  6. /*
  7.  * Copyright (c) 1992 Purdue University
  8.  * All rights reserved.
  9.  *
  10.  * Redistribution and use in source and binary forms are permitted
  11.  * provided that the above copyright notice and this paragraph are
  12.  * duplicated in all such forms and that any documentation,
  13.  * advertising materials, and other materials related to such
  14.  * distribution and use acknowledge that the software was developed
  15.  * by Purdue University.  The name of the University may not be used
  16.  * to endorse or promote products derived * from this software without
  17.  * specific prior written permission.
  18.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  19.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  20.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  21.  *
  22.  * Note: this copyright applies to portions of this software developed
  23.  * at Purdue beyond the software covered by the original copyright.
  24.  */
  25. #include <sys/types.h>
  26.  
  27. #ifndef LOADABLE
  28. #include "dp.h"
  29. #endif
  30.  
  31. #if NDP > 0
  32. #define    STREAMS    1
  33. #define    DEBUGS    1
  34. #include <sys/param.h>
  35. #include <sys/stream.h>
  36. #include <sys/stropts.h>
  37. #include <sys/dir.h>
  38. #include <sys/signal.h>
  39. #include <sys/user.h>
  40. #include <sys/mbuf.h>
  41. #include <sys/socket.h>
  42. #include <net/if.h>
  43. #include <net/route.h>
  44. #ifdef    LOADABLE
  45. #include "if_ppp.h"
  46. #include "ppp_str.h"
  47. #else
  48. #include <sys/if_ppp.h>
  49. #include <sys/ppp_str.h>
  50. #endif
  51.  
  52. #ifdef    DEBUGS
  53. #include <sys/syslog.h>
  54. #define    DLOG(s,a)    if(ppp_async_debug) log(LOG_INFO, s, a)
  55. int    ppp_async_debug=0;
  56. int    ppp_async_input_debug=0;
  57. #define MAX_DUMP_BYTES 1504
  58. #else
  59. #define    DLOG(s)    {}
  60. #endif
  61.  
  62. #ifdef LOADABLE
  63. #include <sys/conf.h>
  64. #include <sys/buf.h>
  65. #include <sundev/mbvar.h>
  66. #include <sun/autoconf.h>
  67. #include <sun/vddrv.h>
  68.  
  69. static int ppp_async_cnt = NDP;
  70. #endif
  71.  
  72.  
  73. static    int    ppp_async_open(), ppp_async_close(), ppp_async_rput(), ppp_async_wput(),
  74.         ppp_async_wsrv(), ppp_async_rsrv();
  75.  
  76. static     struct    module_info    minfo ={
  77.     0xabcd, "pppasync" ,0, INFPSZ, 16384, 4096
  78. };
  79.  
  80. static    struct    qinit    r_init = {
  81.     ppp_async_rput, ppp_async_rsrv, ppp_async_open, ppp_async_close, NULL, &minfo, NULL
  82. };
  83. static    struct    qinit    w_init = {
  84.     ppp_async_wput, ppp_async_wsrv, ppp_async_open, ppp_async_close, NULL, &minfo, NULL
  85. };
  86. struct    streamtab    ppp_asyncinfo = {
  87.     &r_init, &w_init, NULL, NULL, NULL
  88. };
  89.  
  90. /*
  91.  * FCS lookup table as calculated by genfcstab.
  92.  */
  93. static u_short fcstab[256] = {
  94.     0x0000,    0x1189,    0x2312,    0x329b,    0x4624,    0x57ad,    0x6536,    0x74bf,
  95.     0x8c48,    0x9dc1,    0xaf5a,    0xbed3,    0xca6c,    0xdbe5,    0xe97e,    0xf8f7,
  96.     0x1081,    0x0108,    0x3393,    0x221a,    0x56a5,    0x472c,    0x75b7,    0x643e,
  97.     0x9cc9,    0x8d40,    0xbfdb,    0xae52,    0xdaed,    0xcb64,    0xf9ff,    0xe876,
  98.     0x2102,    0x308b,    0x0210,    0x1399,    0x6726,    0x76af,    0x4434,    0x55bd,
  99.     0xad4a,    0xbcc3,    0x8e58,    0x9fd1,    0xeb6e,    0xfae7,    0xc87c,    0xd9f5,
  100.     0x3183,    0x200a,    0x1291,    0x0318,    0x77a7,    0x662e,    0x54b5,    0x453c,
  101.     0xbdcb,    0xac42,    0x9ed9,    0x8f50,    0xfbef,    0xea66,    0xd8fd,    0xc974,
  102.     0x4204,    0x538d,    0x6116,    0x709f,    0x0420,    0x15a9,    0x2732,    0x36bb,
  103.     0xce4c,    0xdfc5,    0xed5e,    0xfcd7,    0x8868,    0x99e1,    0xab7a,    0xbaf3,
  104.     0x5285,    0x430c,    0x7197,    0x601e,    0x14a1,    0x0528,    0x37b3,    0x263a,
  105.     0xdecd,    0xcf44,    0xfddf,    0xec56,    0x98e9,    0x8960,    0xbbfb,    0xaa72,
  106.     0x6306,    0x728f,    0x4014,    0x519d,    0x2522,    0x34ab,    0x0630,    0x17b9,
  107.     0xef4e,    0xfec7,    0xcc5c,    0xddd5,    0xa96a,    0xb8e3,    0x8a78,    0x9bf1,
  108.     0x7387,    0x620e,    0x5095,    0x411c,    0x35a3,    0x242a,    0x16b1,    0x0738,
  109.     0xffcf,    0xee46,    0xdcdd,    0xcd54,    0xb9eb,    0xa862,    0x9af9,    0x8b70,
  110.     0x8408,    0x9581,    0xa71a,    0xb693,    0xc22c,    0xd3a5,    0xe13e,    0xf0b7,
  111.     0x0840,    0x19c9,    0x2b52,    0x3adb,    0x4e64,    0x5fed,    0x6d76,    0x7cff,
  112.     0x9489,    0x8500,    0xb79b,    0xa612,    0xd2ad,    0xc324,    0xf1bf,    0xe036,
  113.     0x18c1,    0x0948,    0x3bd3,    0x2a5a,    0x5ee5,    0x4f6c,    0x7df7,    0x6c7e,
  114.     0xa50a,    0xb483,    0x8618,    0x9791,    0xe32e,    0xf2a7,    0xc03c,    0xd1b5,
  115.     0x2942,    0x38cb,    0x0a50,    0x1bd9,    0x6f66,    0x7eef,    0x4c74,    0x5dfd,
  116.     0xb58b,    0xa402,    0x9699,    0x8710,    0xf3af,    0xe226,    0xd0bd,    0xc134,
  117.     0x39c3,    0x284a,    0x1ad1,    0x0b58,    0x7fe7,    0x6e6e,    0x5cf5,    0x4d7c,
  118.     0xc60c,    0xd785,    0xe51e,    0xf497,    0x8028,    0x91a1,    0xa33a,    0xb2b3,
  119.     0x4a44,    0x5bcd,    0x6956,    0x78df,    0x0c60,    0x1de9,    0x2f72,    0x3efb,
  120.     0xd68d,    0xc704,    0xf59f,    0xe416,    0x90a9,    0x8120,    0xb3bb,    0xa232,
  121.     0x5ac5,    0x4b4c,    0x79d7,    0x685e,    0x1ce1,    0x0d68,    0x3ff3,    0x2e7a,
  122.     0xe70e,    0xf687,    0xc41c,    0xd595,    0xa12a,    0xb0a3,    0x8238,    0x93b1,
  123.     0x6b46,    0x7acf,    0x4854,    0x59dd,    0x2d62,    0x3ceb,    0x0e70,    0x1ff9,
  124.     0xf78f,    0xe606,    0xd49d,    0xc514,    0xb1ab,    0xa022,    0x92b9,    0x8330,
  125.     0x7bc7,    0x6a4e,    0x58d5,    0x495c,    0x3de3,    0x2c6a,    0x1ef1,    0x0f78
  126. };
  127.  
  128.  
  129. struct  ppp_async_info {
  130.     u_int    pai_flags;
  131. #define    PAI_FLAGS_INUSE        0x1
  132. #define    PAI_FLAGS_FLUSH        0x2
  133. #define    PAI_FLAGS_ESCAPED     0x4
  134. #define    PAI_FLAGS_COMPPROT    0x8
  135. #define    PAI_FLAGS_COMPAC    0x10
  136.  
  137.     u_long    pai_asyncmap;            /* current outgoing asyncmap */
  138.     int    pai_buffsize;            /* how big of an input buffer to alloc */
  139.     int    pai_buffcount;            /* how many chars currently in the input buffer */
  140.     u_short    pai_fcs;            /* the current fcs */
  141.     mblk_t    *pai_buffer;            /* pointer to the current buffer list */
  142.     mblk_t    *pai_bufftail;            /* pointer to the current input block */
  143. };
  144.  
  145. typedef    struct ppp_async_info    PAI;
  146.  
  147. static PAI pai[NDP];        /* our private cache of async control structures */
  148.  
  149.  
  150.  
  151. /* an open function might fail if we don't have any
  152.  * more pai elements left free 
  153.  */
  154.  
  155. static int
  156. ppp_async_open(q, dev, flag, sflag)
  157.     queue_t    *q;
  158.     dev_t    dev;
  159.     int    flag,
  160.         sflag;
  161. {
  162.     register PAI    *p;
  163.     register int x;
  164.     int    s;
  165.  
  166.     if(!suser()) {
  167.         u.u_error = EPERM;
  168.         return(OPENFAIL);    /* only let the superuser or setuid
  169.                      * root open this module */
  170.     }
  171.     
  172.     if(q->q_ptr) {
  173.         u.u_error = EBUSY;
  174.         return(OPENFAIL);
  175.     }
  176.     s = splstr();
  177.     if(!q->q_ptr) {
  178.         for(x=0; x < NDP; x++)     /* search for an empty PAI */
  179.             if(!(pai[x].pai_flags & PAI_FLAGS_INUSE))
  180.                 break;
  181.         if(x == NDP)    {        /* all buffers in use */
  182.             splx(s);        /* restore processor state */
  183.             u.u_error = ENOBUFS;
  184.             return (OPENFAIL);
  185.         }
  186.         p = &pai[x];
  187.         DLOG("ppp_async%d: opening\n",x);
  188.     }
  189.     else {
  190.         p = (PAI *) q->q_ptr;
  191.         DLOG("ppp_async%d: reopen\n", (p-pai)/sizeof(PAI));
  192.     }
  193.     WR(q)->q_ptr = q->q_ptr =  (caddr_t) p;    /* point the write Q and this read Q to private data. */            
  194.     p->pai_flags = PAI_FLAGS_INUSE;
  195.     p->pai_asyncmap = 0xffffffff;        /* default async map */
  196.     p->pai_buffsize = PPP_MTU + sizeof(struct ppp_header) + 
  197.             sizeof(u_short);    /* how big of a buffer to alloc */
  198.     p->pai_buffcount = 0;            /* number of chars currently in buffer */
  199.     p->pai_buffer = NULL;
  200.     splx(s);
  201.     return(0);
  202. }
  203.  
  204. static int
  205. ppp_async_close(q)
  206.     queue_t    *q;            /* queue info */
  207. {
  208.     int    s;
  209.     register PAI     *p;
  210.  
  211.     s = splstr();
  212.     if(p = (PAI *) q->q_ptr) {
  213.         p->pai_flags = 0;    /* clear all flags */
  214.         if(p->pai_buffer) {    /* currently receiving some chars, discard the buffer */
  215.             freemsg(p->pai_buffer);
  216.             p->pai_buffer = NULL;
  217.         }
  218.         DLOG("ppp_async%d: closing\n",(p-pai)/sizeof(PAI));
  219.     }
  220.     splx(s);
  221.     return(0);            
  222. }
  223.  
  224.  
  225. static int
  226. ppp_async_wput(q, mp)
  227.     queue_t  *q;
  228.     register mblk_t *mp;
  229.  
  230. /* M_IOCTL processing is performed at this level. There is some weirdness here, but I couldn't
  231. think of an easier way to handle it.
  232.  
  233.    SIOCSIFASYNCMAP and SIOCGIFASYNCMAP is handled here.
  234.  
  235.    SIOCSIFCOMPAC and SIOCSIFCOMPPROT are both handled here, rather than jamming new flag bits
  236.    into the if_ interface.  However the upper ppp_if.c module will set COMPAC and
  237.    COMPPROT flags too, it just doesn't generate the IOACK.
  238.  
  239.    SIOCSIFMRU and SIOCGIFMRU (Max Receive Unit) are both handled here.
  240.    Rather than using the MTU to set the MRU, we have a seperate IOCTL for it.
  241.  
  242. */
  243. {
  244.  
  245.     register struct iocblk    *i;
  246.     register PAI    *p;
  247.     int    x;
  248.  
  249.     switch (mp->b_datap->db_type) {
  250.  
  251.         case     M_FLUSH :
  252.             if(*mp->b_rptr & FLUSHW)
  253.                 flushq(q, FLUSHDATA);
  254.             putnext(q, mp);        /* send it along too */
  255.             break;
  256.  
  257.         case    M_DATA :
  258.             putq(q, mp);    /* queue it for my service routine */
  259.             break;
  260.  
  261.         case    M_IOCTL :
  262.             i = (struct iocblk *) mp->b_rptr;
  263.             p =  (PAI *) q->q_ptr;
  264.             switch (i->ioc_cmd) {
  265.  
  266.                 case SIOCSIFCOMPAC :    /* enable or disable AC compression */
  267.                     if(i->ioc_count != sizeof(u_char)) {
  268.                         i->ioc_error = EINVAL;
  269.                         goto iocnak;
  270.                     }
  271.                     DLOG("ppp_async: SIFCOMPAC %d\n",*(u_char *) mp->b_cont->b_rptr);
  272.                     if( *(u_char *) mp->b_cont->b_rptr) 
  273.                         p->pai_flags |= PAI_FLAGS_COMPAC;
  274.                     else
  275.                         p->pai_flags &= ~PAI_FLAGS_COMPAC;
  276.                     i->ioc_count = 0;
  277.                     goto iocack;
  278.                 case SIOCSIFCOMPPROT:    /* enable or disable PROT  compression */
  279.                     if(i->ioc_count != sizeof(u_char)) {
  280.                         i->ioc_error = EINVAL;
  281.                         goto iocnak;
  282.                     }
  283.  
  284.                     DLOG("ppp_async: SIFCOMPPROT %d\n",*(u_char *) mp->b_cont->b_rptr);
  285.                     if( *(u_char *) mp->b_cont->b_rptr) 
  286.                         p->pai_flags |= PAI_FLAGS_COMPPROT;
  287.                     else
  288.                         p->pai_flags &= ~PAI_FLAGS_COMPPROT;
  289.                     i->ioc_count = 0;
  290.                     goto iocack;
  291.  
  292.  
  293.                 case SIOCSIFMRU     :
  294.                     if(i->ioc_count != sizeof(int)) {
  295.                         i->ioc_error = EINVAL;
  296.                         goto iocnak;
  297.                     }
  298.                     x = *(int *) mp->b_cont->b_rptr;
  299.                     if(x < PPP_MTU)
  300.                         x = PPP_MTU;
  301.                     x += sizeof(struct ppp_header) + sizeof(u_short);
  302.                     if(x > 4096) { /* couldn't allocb something this big */
  303.                         i->ioc_error = EINVAL;
  304.                         goto iocnak;
  305.                     }
  306.                     p->pai_buffsize = x;
  307.  
  308.                     i->ioc_count  = 0;
  309.                     goto iocack;
  310.                 case SIOCGIFMRU :
  311.                     if(mp->b_cont = allocb(sizeof(int), BPRI_MED)) {
  312.                         *(int *) mp->b_cont->b_wptr = 
  313.                             p->pai_buffsize - (sizeof(struct ppp_header) + 
  314.                             sizeof(u_short));
  315.                         mp->b_cont->b_wptr += i->ioc_count  = sizeof(int);
  316.                         goto iocack;
  317.                     }
  318.                     i->ioc_error = ENOSR;
  319.                     goto iocnak;
  320.  
  321.                 case SIOCGIFASYNCMAP :
  322.                     if(mp->b_cont = allocb(sizeof(u_long), BPRI_MED)) {
  323.                         *(u_long *) mp->b_cont->b_wptr = p->pai_asyncmap;
  324.                         mp->b_cont->b_wptr += i->ioc_count = sizeof(u_long);
  325.                         goto iocack;
  326.                     }
  327.                     i->ioc_error = ENOSR;
  328.                     goto iocnak;
  329.                         
  330.                 case SIOCSIFASYNCMAP :
  331.                     
  332.                     if(i->ioc_count != sizeof(u_long)) {
  333.                         i->ioc_error = EINVAL;
  334.                         goto iocnak;    /* ugh, goto */
  335.                     }
  336.                     DLOG("ppp_async: SIFASYNCMAP %lx\n",*(u_long *) mp->b_cont->b_rptr);
  337.     
  338.                     p->pai_asyncmap = *(u_long *) mp->b_cont->b_rptr;
  339.                     i->ioc_count = 0;
  340. iocack:;
  341.                     mp->b_datap->db_type = M_IOCACK;
  342.                     qreply(q,mp);
  343.                     break;
  344. iocnak:;
  345.                     i->ioc_count = 0;
  346.                     mp->b_datap->db_type = M_IOCNAK;
  347.                     qreply(q, mp);
  348.                     break;
  349.                 default:        /* unknown IOCTL call */
  350.                     putnext(q,mp);    /* pass it along */
  351.             }
  352.             break;        
  353.         default :
  354.             putnext(q,mp);    /* don't know what to do with this, so send it along*/
  355.     }
  356. }
  357.  
  358. static int
  359. ppp_async_wsrv(q)
  360.     queue_t    *q;
  361.  
  362. /* this is an incredibly ugly routine. If you see a better way of doing this, feel free
  363.    to improve it. I'm hoping that the buffer management routines are efficient, in terms
  364.    of dup'ing and adjusting message blocks. Hopefully we won't run out of small message
  365.     blocks. Perhaps some counters should be kept to record how efficient this routine
  366.    is, and how much break up of messages is required. 
  367.  
  368.    I'm not doing anything funny with stuffing PPP_ESCAPES into the actual data buffers.
  369.    If you get a lot of outgoing errors .. you might need to up your
  370.    NBLK4 parameter by quite a bit.... (see param.c)
  371. */
  372. {
  373.     register u_char    *cp;
  374.     register PAI    *p;
  375.     register u_short    fcs;
  376.     register mblk_t *mp;
  377.     u_char        *start, *stop,c;
  378.     mblk_t    *m1, *m0, *outgoing;
  379.  
  380.     while((mp = getq(q)) != NULL) {
  381.         /* we can only get M_DATA types into our Queue, due to our Put function */
  382.         if(!canput(q->q_next)) {
  383.             putbq(q, mp);
  384.             return;
  385.         }
  386.         if(msgdsize(mp) < (sizeof(u_char) + sizeof(u_short))) {    /* at least a protocol
  387.                                     and FCS required */
  388.             freemsg(mp);    /* discard the message */
  389.             putctl1(OTHERQ(q), M_CTL, IF_OUTPUT_ERROR);    /* indicate an output error */
  390.             continue;
  391.         }
  392.         m0 = mp;    /* remember first message block */
  393.         p = (PAI *) q->q_ptr;
  394.         outgoing = NULL;
  395.         fcs = PPP_INITFCS;
  396. #define    SPECIAL(p,c)    ((c) == PPP_FLAG) || ((c) == PPP_ESCAPE) ||  \
  397.                 ((c) < 0x20 && ((p)->pai_asyncmap & (1 << (c))))
  398.  
  399.         /* for each block in the message, scan between the start and stop
  400.             markers for escaped chars. dup the message block and chain in
  401.             the PPP_ESCAPE char and the PPP_TRANS'd character. Continue processing
  402.             for all of this data block, then for all remaining blocks
  403.         */
  404.         while(mp) {
  405.             start = mp->b_rptr;
  406.             stop = mp->b_wptr;
  407.             while(start < stop )     {
  408.                 for(cp = start; cp < stop; cp++) {
  409.                     if(SPECIAL(p,*cp))
  410.                         break;
  411.                     fcs = PPP_FCS(fcs, *cp);
  412.                 }
  413.                     
  414.                 if(cp - start) {
  415.                     /* dup the message block, up to len chars */
  416. #define    WORKAROUND_DB_REF_BUG
  417. #ifdef    WORKAROUND_DB_REF_BUG
  418.                     m1 = (mp->b_datap->db_ref < 255) 
  419.                        ? dupb(mp)
  420.                        : copyb(mp);
  421. #else
  422.                     m1 = dupb(mp);
  423. #endif
  424.                     if(!m1)
  425.                         goto nobuffs;
  426.  
  427.                      /* discard chars at front */
  428.                     adjmsg(m1, start - mp->b_rptr);
  429.  
  430.                     /* throw away remaining chars */
  431.                     adjmsg(m1,  cp - stop);
  432.                     if(outgoing)
  433.                         linkb(outgoing, m1);
  434.                     else
  435.                         outgoing = m1;
  436.                 } 
  437.                 if(cp < stop) {    /* a special char must follow */
  438.                     m1 = allocb(2 * sizeof(u_char),BPRI_LO);
  439.                     if(!m1)
  440.                         goto nobuffs;
  441.                     *m1->b_wptr++ = PPP_ESCAPE;
  442.                     *m1->b_wptr++ = *cp ^ PPP_TRANS;
  443.                     fcs = PPP_FCS(fcs, *cp);
  444.                     if(outgoing)
  445.                         linkb(outgoing, m1);
  446.                     else
  447.                         outgoing = m1;
  448.                 }
  449.                 else
  450.                     break;    /* no sense in doing another add and 
  451.                            compare */
  452.                 start = cp + 1;
  453.             }  /* end while start < stop */
  454.             mp = mp->b_cont;    /* look at the next block */
  455.         } /* end while(mp) */
  456.         m1 = allocb(sizeof(u_char) + 2 * sizeof(u_short), BPRI_LO);
  457.         if(!m1)
  458.             goto nobuffs;
  459.         fcs ^= 0xffff;            /* XOR the resulting FCS */
  460.         c = fcs & 0xff;
  461.         if(SPECIAL(p,c)) {
  462.             *m1->b_wptr++ = PPP_ESCAPE;
  463.             *m1->b_wptr++ = c ^ PPP_TRANS;
  464.         }
  465.         else
  466.             *m1->b_wptr++ = c;
  467.         c = fcs >> 8;
  468.         if(SPECIAL(p,c)) {
  469.             *m1->b_wptr++ = PPP_ESCAPE;
  470.             *m1->b_wptr++ = c ^ PPP_TRANS;
  471.         }
  472.         else
  473.             *m1->b_wptr++  = c;
  474.  
  475.         *m1->b_wptr++ = PPP_FLAG;    /* add trailing PPP_FLAG */
  476.         linkb(outgoing, m1);        /* gee, we better have an outgoing by now */
  477.         /* now we check to see if the lower queue has entries, if so, we assume
  478.             that we don't need a leading PPP_FLAG because these packets
  479.             will be sent back to back */
  480.         if(!qsize(q->q_next)) {    /* no entries in next queue, have to add a leading 
  481.                       PPP_FLAG */
  482.             m1 = allocb(sizeof(u_char), BPRI_LO);
  483.             if(!m1)
  484.                 goto nobuffs;
  485.             *m1->b_wptr++ = PPP_FLAG;
  486.             linkb(m1, outgoing);
  487.             outgoing = m1;
  488.         }
  489.         /* phew, ready to ship */
  490.         putnext(q, outgoing);
  491.         freemsg(m0);        /* discard original message block pointers */
  492.         continue;
  493. nobuffs:;    /* well, we ran out of memory somewhere */
  494.         if(outgoing)
  495.             freemsg(outgoing);        /* throw away what we have already */
  496.         putbq(q, m0);                /* put back the original message */
  497.         putctl1(OTHERQ(q), M_CTL, IF_OUTPUT_ERROR);
  498.         qenable(q);                /* reschedule ourselves for later */
  499.         return;
  500.     } /* end while(getq()) */
  501. }    /* end function */                    
  502.  
  503. static int
  504. ppp_async_rput(q, mp)
  505.     queue_t *q;
  506.     register mblk_t *mp;
  507. {
  508.  
  509.     switch (mp->b_datap->db_type) {
  510.  
  511.         case     M_FLUSH :
  512.             if(*mp->b_rptr & FLUSHR)
  513.                 flushq(q, FLUSHDATA);
  514.             putnext(q, mp);        /* send it along too */
  515.             break;
  516.  
  517.         case    M_DATA :
  518.             putq(q, mp);    /* queue it for my service routine */
  519.             break;
  520.  
  521.         default :
  522.             putnext(q,mp);    /* don't know what to do with this, so send it along*/
  523.     }
  524. }
  525.  
  526. static int
  527. ppp_async_rsrv(q)
  528.     queue_t    *q;
  529. {
  530.     register mblk_t *mp;
  531.     register PAI    *p;
  532.     register u_char    *cp,c;
  533.     mblk_t    *m0;
  534.  
  535.     p = (PAI *) q->q_ptr;
  536. #define    INPUT_ERROR(q)    putctl1(q, M_CTL, IF_INPUT_ERROR)
  537. #define    STUFF_CHAR(p,c)    (*(p)->pai_bufftail->b_wptr++ = (c), (p)->pai_buffcount++)
  538. #define    FLUSHEM(q,p)    (INPUT_ERROR(q), (p)->pai_flags |= PAI_FLAGS_FLUSH)
  539.  
  540.     while((mp = getq(q)) != NULL) {
  541.         /* we can only get M_DATA types into our Queue, due to our Put function */
  542.         if(!canput(q->q_next)) {
  543.             putbq(q, mp);
  544.             return;
  545.         }
  546.         m0 = mp;    /* remember first message block */
  547.         for(; mp != NULL; mp = mp->b_cont) {    /* for each message block */
  548.             cp = mp->b_rptr;
  549.             while(cp < mp->b_wptr) {
  550.                 c = *cp++;
  551.                 if(c == PPP_FLAG) {
  552.                     p->pai_flags &= ~PAI_FLAGS_FLUSH;    /* clear flush indicater */
  553.                     
  554.                     if(p->pai_buffcount > sizeof(u_short)) { /* discard FCS */
  555.                         adjmsg(p->pai_buffer, -sizeof(u_short));
  556.                         p->pai_buffcount -= sizeof(u_short);
  557.                     }
  558.                     if(p->pai_buffcount < sizeof(struct ppp_header)) {
  559.                         if(p->pai_buffcount) {
  560.                             INPUT_ERROR(q);
  561.                             DLOG("ppp_async: short packet\n",0);
  562.                         }
  563.                         p->pai_buffcount = 0;
  564.                         continue;
  565.                     }
  566.                     if(p->pai_buffer) {
  567.           if(p->pai_fcs == PPP_GOODFCS) {
  568. #if DEBUGS
  569. /*
  570.  * here is where we will dump out a frame in hex using the log()
  571.  * function if ppp_async_input_debug is non-zero. As this function is
  572.  * a pig, we only print up to the number of bytes specified by the value of
  573.  * the ppp_async_input_debug variable so as to not cause too many
  574.  * timeouts.   <gmc@quotron.com>
  575.  */
  576.  
  577.             if (ppp_async_input_debug > 0) {
  578.               register mblk_t *mptr = p->pai_buffer;
  579.               register u_char *rptr;
  580.               register u_int i, mlen;
  581.               u_int frame_length = (unsigned) p->pai_buffcount;
  582.               char buf[2*MAX_DUMP_BYTES+4];   /* tmp buffer */
  583.               char *bp = buf;
  584.               static char digits[] = "0123456789abcdef";
  585.  
  586.               log(LOG_INFO, "ppp_async: got input frame of %d bytes\n", frame_length);
  587.               rptr = mptr->b_rptr; /* get pointer to beginning  */
  588.               mlen = mptr->b_wptr - rptr; /* get length of this dblock */
  589.  
  590.               /* only dump up to MAX_DUMP_BYTES */
  591.  
  592.               i = (frame_length < ppp_async_input_debug) ? frame_length :
  593.                 ppp_async_input_debug;
  594.  
  595.               while (i--) {   /* convert to ascii hex */
  596.                 if (mlen-- == 0) {/* get next dblock */
  597.                   mptr = mptr->b_cont;
  598.                   if (mptr) { /* are we done? */
  599.                     rptr = mptr->b_rptr; /* nope, get next dblock */
  600.                     mlen = mptr->b_wptr - rptr;
  601.                   }
  602.                   else {      /* no more dblocks */
  603.                     if (i != 0)
  604.                       log(LOG_ERR, "ppp_async: ran out of data! (this shouldn't happen\n");
  605.                     break;
  606.                   }
  607.                 }
  608.                 *bp++ = digits[*rptr >> 4]; /* convert byte to ascii hex */
  609.                 *bp++ = digits[*rptr++ & 0xf];
  610.               }
  611.  
  612.               /* add a '>' to show that frame was truncated*/
  613.               if (ppp_async_input_debug < frame_length)
  614.                 *bp++ = '>';
  615.               *bp = 0;
  616.               log(LOG_INFO,"ppp_async: %s\n", buf);
  617.             }
  618. #endif /*DEBUGS*/
  619.                             putnext(q, p->pai_buffer);
  620.     }
  621.                         else {
  622.                             INPUT_ERROR(q);
  623.                             freemsg(p->pai_buffer);
  624.                             DLOG("ppp_async: FCS Error\n",0);
  625.         /* we could be discarding this buffer because of data errors
  626.            in which case we could have kept it, however we might
  627.            also be discarding it because it was too small. so
  628.            we throw it away and the next allocation will be the
  629.            correct size
  630.         */
  631.                         }
  632.                         p->pai_buffer = NULL;
  633.                         p->pai_buffcount  = 0;
  634.                         continue;
  635.                     }
  636.                 }     /* c == PPP_FLAG */
  637.                 else if (p->pai_flags & PAI_FLAGS_FLUSH)
  638.                     continue;            /* skipping chars */
  639.                 else if (c == PPP_ESCAPE) {
  640.                     p->pai_flags |= PAI_FLAGS_ESCAPED;
  641.                     continue;
  642.                 }
  643.  
  644.                 if(p->pai_flags & PAI_FLAGS_ESCAPED) {
  645.                     p->pai_flags &= ~PAI_FLAGS_ESCAPED;     /* clear esc flag */
  646.                     c ^= PPP_TRANS;        /* xor's are cool */
  647.                 }
  648.  
  649.                 /* here we check to see if we have a buffer. If we don't, we assume
  650.                    that this is the first char for the buffer, and we allocb one */
  651.  
  652.                 if(!p->pai_buffer) {
  653.                     /* we allocate buffer chains in blocks of ALLOCBSIZE */
  654.             
  655.                     if(!(p->pai_buffer = allocb(ALLOCBSIZE, BPRI_MED))) {
  656.                         FLUSHEM(q,p);
  657.                         continue;
  658.                         /* if we don't get a buffer, is there some way
  659.                            to recover and requeue later? rather than flushing
  660.                             the current packet... ? */
  661.                     }
  662.                     p->pai_bufftail = p->pai_buffer;
  663.                 }
  664.                 if(!p->pai_buffcount) {
  665.                     p->pai_fcs = PPP_INITFCS;
  666.                     if(c != PPP_ALLSTATIONS) {
  667.                         if(p->pai_flags & PAI_FLAGS_COMPAC) {
  668.                             STUFF_CHAR(p,PPP_ALLSTATIONS);
  669.                             STUFF_CHAR(p,PPP_UI);
  670.                         }
  671.                         else {
  672.                             DLOG("ppp_async: missed ALLSTATIONS\n",0);
  673.                             FLUSHEM(q,p);
  674.                             continue;
  675.                         }
  676.                     }
  677.                 } /* end if !p->pai_buffcount */
  678.                 if(p->pai_buffcount == 1 && c != PPP_UI) {
  679.                     DLOG("ppp_async: missed UI\n",0);
  680.                     FLUSHEM(q,p);
  681.                     continue;
  682.                 }
  683.                 if(p->pai_buffcount == 2 && (c & 1) == 1) {
  684.                     if(p->pai_flags & PAI_FLAGS_COMPPROT)
  685.                         STUFF_CHAR(p, 0);
  686.                     else {
  687.                         DLOG("ppp_async: bad protocol high byte\n",0);
  688.                         FLUSHEM(q,p);
  689.                         continue;
  690.                     }
  691.                 }
  692.                 if(p->pai_buffcount == 3 && (c & 1) == 0) {
  693.                     DLOG("ppp_async: bad protocol low byte\n",0);
  694.                     FLUSHEM(q,p);
  695.                     continue;
  696.                 }
  697.                 if(p->pai_buffcount >= p->pai_buffsize)    {    /* overrun */
  698.                     DLOG("ppp_async: too many chars in input buffer %d\n", p->pai_buffcount);
  699.                     FLUSHEM(q,p);
  700.                     continue;
  701.                 }
  702.                 /* determine if we have enough space in the buffer */
  703.                 if(p->pai_bufftail->b_wptr >= p->pai_bufftail->b_datap->db_lim) {
  704.                     if(p->pai_bufftail = allocb(ALLOCBSIZE, BPRI_MED)) 
  705.                         linkb(p->pai_buffer, p->pai_bufftail);
  706.                     else {
  707.                         DLOG("ppp_async: couldn't get buffer for tail\n",0);
  708.                         FLUSHEM(q,p);    /* discard all of it */
  709.                         continue;
  710.                     }
  711.                  }
  712.                 STUFF_CHAR(p,c);
  713.                 p->pai_fcs = PPP_FCS(p->pai_fcs, c);
  714.             } /* end while cp  < wptr */
  715.         }    /* end for each block */
  716.         /* discard this message now */
  717.         freemsg(m0);
  718.     }    /* end while  getq */
  719.  
  720. }
  721.  
  722.  
  723. #ifdef    LOADABLE
  724.  
  725. #define LOG_INUSE 1
  726.  
  727.  
  728. static struct log { 
  729.     char flags;
  730.     char nr;
  731. } ppp_async_log[NDP];
  732.  
  733. static struct vdldrv ppp_async_vd = {
  734.     VDMAGIC_PSEUDO,
  735.     "Dialup PPP Async",
  736.     NULL,
  737.     NULL,
  738.     NULL,
  739.     0,
  740.     0,
  741. };
  742.  
  743. extern struct rtentry *rtable;
  744.  
  745. ppp_async_init(fc,vdp,vdi,vds)
  746. unsigned int fc;
  747. struct vddrv *vdp;
  748. addr_t vdi;
  749. struct vdstat *vds;
  750. {
  751.     static struct fmodsw *fmod_ppp_async;
  752.  
  753.     switch(fc) {
  754.         case VDLOAD:
  755.         {
  756.             int dev,i;
  757.             for(dev = 0; dev < fmodcnt; dev++) {
  758.                 if(fmodsw[dev].f_str == NULL)
  759.                     break;
  760.             }
  761.             if(dev == fmodcnt)
  762.                 return(ENODEV);
  763.             fmod_ppp_async = &fmodsw[dev];
  764.             for(i = 0; i <= FMNAMESZ; i++)
  765.                 fmod_ppp_async->f_name[i] = minfo.mi_idname[i];
  766.             fmod_ppp_async->f_str = &ppp_asyncinfo;
  767.             vdp->vdd_vdtab = (struct vdlinkage *) &ppp_async_vd;
  768.         }
  769.             return 0;
  770.         case VDUNLOAD:
  771.             {
  772.             int dev;
  773.             for (dev = 0; dev < ppp_async_cnt; dev++) 
  774.                 if (ppp_async_log[dev].flags & LOG_INUSE)
  775.                     return (EIO);
  776.             }
  777.             fmod_ppp_async->f_name[0] = '\0';
  778.             fmod_ppp_async->f_str = NULL;
  779.             return 0;
  780.         case VDSTAT:
  781.             return 0;
  782.         default:
  783.             return EIO;
  784.     }
  785. }
  786. #endif /* LOADABLE */
  787.  
  788. #endif
  789.