5bd2fa83fb686220fcac733a6b51d0cbc2ac8f8b
[ppp.git] / solaris / ppp_ahdlc.c
1 /*
2  * ppp_ahdlc.c - STREAMS module for doing PPP asynchronous HDLC.
3  *
4  * Re-written by Adi Masputra <adi.masputra@sun.com>, based on 
5  * the original ppp_ahdlc.c
6  *
7  * Copyright (c) 2000 by Sun Microsystems, Inc.
8  * All rights reserved.
9  *
10  * Permission to use, copy, modify, and distribute this software and its
11  * documentation is hereby granted, provided that the above copyright
12  * notice appears in all copies.  
13  *
14  * SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF
15  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
16  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
17  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT.  SUN SHALL NOT BE LIABLE FOR
18  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
19  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES
20  *
21  * Copyright (c) 1994 Paul Mackerras. All rights reserved.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  *
27  * 1. Redistributions of source code must retain the above copyright
28  *    notice, this list of conditions and the following disclaimer.
29  *
30  * 2. Redistributions in binary form must reproduce the above copyright
31  *    notice, this list of conditions and the following disclaimer in
32  *    the documentation and/or other materials provided with the
33  *    distribution.
34  *
35  * 3. The name(s) of the authors of this software must not be used to
36  *    endorse or promote products derived from this software without
37  *    prior written permission.
38  *
39  * 4. Redistributions of any form whatsoever must retain the following
40  *    acknowledgment:
41  *    "This product includes software developed by Paul Mackerras
42  *     <paulus@samba.org>".
43  *
44  * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
45  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
46  * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
47  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
48  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
49  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
50  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
51  *
52  * $Id: ppp_ahdlc.c,v 1.3 2002/12/06 09:49:16 paulus Exp $
53  */
54
55 /*
56  * This file is used under Solaris 2, SVR4, SunOS 4, and Digital UNIX.
57  */
58 #include <sys/types.h>
59 #include <sys/param.h>
60 #include <sys/stream.h>
61 #include <sys/errno.h>
62
63 #ifdef SVR4
64 #include <sys/conf.h>
65 #include <sys/kmem.h>
66 #include <sys/cmn_err.h>
67 #include <sys/ddi.h>
68 #else
69 #include <sys/user.h>
70 #ifdef __osf__
71 #include <sys/cmn_err.h>
72 #endif
73 #endif /* SVR4 */
74
75 #include <net/ppp_defs.h>
76 #include <net/pppio.h>
77 #include "ppp_mod.h"
78
79 /*
80  * Right now, mutex is only enabled for Solaris 2.x
81  */
82 #if defined(SOL2)
83 #define USE_MUTEX
84 #endif /* SOL2 */
85
86 /*
87  * intpointer_t and uintpointer_t are signed and unsigned integer types 
88  * large enough to hold any data pointer; that is, data pointers can be 
89  * assigned into or from these integer types without losing precision.
90  * On recent Solaris releases, these types are defined in sys/int_types.h,
91  * but not on SunOS 4.x or the earlier Solaris versions.
92  */
93 #if defined(_LP64) || defined(_I32LPx)
94 typedef long                    intpointer_t;
95 typedef unsigned long           uintpointer_t;
96 #else
97 typedef int                     intpointer_t;
98 typedef unsigned int            uintpointer_t;
99 #endif
100
101 MOD_OPEN_DECL(ahdlc_open);
102 MOD_CLOSE_DECL(ahdlc_close);
103 static int ahdlc_wput __P((queue_t *, mblk_t *));
104 static int ahdlc_rput __P((queue_t *, mblk_t *));
105 static void ahdlc_encode __P((queue_t *, mblk_t *));
106 static void ahdlc_decode __P((queue_t *, mblk_t *));
107 static int msg_byte __P((mblk_t *, unsigned int));
108
109 #if defined(SOL2)
110 /*
111  * Don't send HDLC start flag is last transmit is within 1.5 seconds -
112  * FLAG_TIME is defined is microseconds
113  */
114 #define FLAG_TIME   1500
115 #define ABS(x)      (x >= 0 ? x : (-x))
116 #endif /* SOL2 */
117
118 /*
119  * Extract byte i of message mp 
120  */
121 #define MSG_BYTE(mp, i) ((i) < (mp)->b_wptr - (mp)->b_rptr? (mp)->b_rptr[i]: \
122                          msg_byte((mp), (i)))
123
124 /* 
125  * Is this LCP packet one we have to transmit using LCP defaults? 
126  */
127 #define LCP_USE_DFLT(mp)        (1 <= (code = MSG_BYTE((mp), 4)) && code <= 7)
128
129 /*
130  * Standard STREAMS declarations
131  */
132 static struct module_info minfo = {
133     0x7d23, "ppp_ahdl", 0, INFPSZ, 32768, 512
134 };
135
136 static struct qinit rinit = {
137     ahdlc_rput, NULL, ahdlc_open, ahdlc_close, NULL, &minfo, NULL
138 };
139
140 static struct qinit winit = {
141     ahdlc_wput, NULL, NULL, NULL, NULL, &minfo, NULL
142 };
143
144 #if defined(SVR4) && !defined(SOL2)
145 int phdldevflag = 0;
146 #define ppp_ahdlcinfo phdlinfo
147 #endif /* defined(SVR4) && !defined(SOL2) */
148
149 struct streamtab ppp_ahdlcinfo = {
150     &rinit,                         /* ptr to st_rdinit */
151     &winit,                         /* ptr to st_wrinit */
152     NULL,                           /* ptr to st_muxrinit */
153     NULL,                           /* ptr to st_muxwinit */
154 #if defined(SUNOS4)
155     NULL                            /* ptr to ptr to st_modlist */
156 #endif /* SUNOS4 */
157 };
158
159 #if defined(SUNOS4)
160 int ppp_ahdlc_count = 0;            /* open counter */
161 #endif /* SUNOS4 */
162
163 /*
164  * Per-stream state structure
165  */
166 typedef struct ahdlc_state {
167 #if defined(USE_MUTEX)
168     kmutex_t        lock;                   /* lock for this structure */
169 #endif /* USE_MUTEX */
170     int             flags;                  /* link flags */
171     mblk_t          *rx_buf;                /* ptr to receive buffer */
172     int             rx_buf_size;            /* receive buffer size */
173     ushort_t        infcs;                  /* calculated rx HDLC FCS */
174     u_int32_t       xaccm[8];               /* 256-bit xmit ACCM */
175     u_int32_t       raccm;                  /* 32-bit rcv ACCM */
176     int             mtu;                    /* interface MTU */
177     int             mru;                    /* link MRU */
178     int             unit;                   /* current PPP unit number */
179     struct pppstat  stats;                  /* statistic structure */
180 #if defined(SOL2)
181     clock_t         flag_time;              /* time in usec between flags */
182     clock_t         lbolt;                  /* last updated lbolt */
183 #endif /* SOL2 */
184 } ahdlc_state_t;
185
186 /*
187  * Values for flags 
188  */
189 #define ESCAPED         0x100   /* last saw escape char on input */
190 #define IFLUSH          0x200   /* flushing input due to error */
191
192 /* 
193  * RCV_B7_1, etc., defined in net/pppio.h, are stored in flags also. 
194  */
195 #define RCV_FLAGS       (RCV_B7_1|RCV_B7_0|RCV_ODDP|RCV_EVNP)
196
197 /*
198  * FCS lookup table as calculated by genfcstab.
199  */
200 static u_short fcstab[256] = {
201         0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
202         0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
203         0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
204         0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
205         0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
206         0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
207         0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
208         0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
209         0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
210         0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
211         0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
212         0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
213         0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
214         0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
215         0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
216         0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
217         0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
218         0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
219         0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
220         0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
221         0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
222         0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
223         0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
224         0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
225         0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
226         0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
227         0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
228         0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
229         0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
230         0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
231         0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
232         0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
233 };
234
235 static u_int32_t paritytab[8] =
236 {
237         0x96696996, 0x69969669, 0x69969669, 0x96696996,
238         0x69969669, 0x96696996, 0x96696996, 0x69969669
239 };
240
241 /*
242  * STREAMS module open (entry) point
243  */
244 MOD_OPEN(ahdlc_open)
245 {
246     ahdlc_state_t   *state;
247
248     /*
249      * Return if it's already opened
250      */
251     if (q->q_ptr) {
252         return 0;
253     }
254
255     /*
256      * This can only be opened as a module
257      */
258     if (sflag != MODOPEN) {
259         return 0;
260     }
261
262     state = (ahdlc_state_t *) ALLOC_NOSLEEP(sizeof(ahdlc_state_t));
263     if (state == 0)
264         OPEN_ERROR(ENOSR);
265     bzero((caddr_t) state, sizeof(ahdlc_state_t));
266
267     q->q_ptr     = (caddr_t) state;
268     WR(q)->q_ptr = (caddr_t) state;
269
270 #if defined(USE_MUTEX)
271     mutex_init(&state->lock, NULL, MUTEX_DEFAULT, NULL);
272     mutex_enter(&state->lock);
273 #endif /* USE_MUTEX */
274
275     state->xaccm[0] = ~0;           /* escape 0x00 through 0x1f */
276     state->xaccm[3] = 0x60000000;   /* escape 0x7d and 0x7e */
277     state->mru      = PPP_MRU;      /* default of 1500 bytes */
278 #if defined(SOL2)
279     state->flag_time = drv_usectohz(FLAG_TIME);
280 #endif /* SOL2 */
281
282 #if defined(USE_MUTEX)
283     mutex_exit(&state->lock);
284 #endif /* USE_MUTEX */  
285
286 #if defined(SUNOS4)
287     ppp_ahdlc_count++;
288 #endif /* SUNOS4 */
289
290     qprocson(q);
291     
292     return 0;
293 }
294
295 /*
296  * STREAMS module close (exit) point
297  */
298 MOD_CLOSE(ahdlc_close)
299 {
300     ahdlc_state_t   *state;
301
302     qprocsoff(q);
303
304     state = (ahdlc_state_t *) q->q_ptr;
305
306     if (state == 0) {
307         DPRINT("state == 0 in ahdlc_close\n");
308         return 0;
309     }
310
311 #if defined(USE_MUTEX)
312     mutex_enter(&state->lock);
313 #endif /* USE_MUTEX */
314
315     if (state->rx_buf != 0) {
316         freemsg(state->rx_buf);
317         state->rx_buf = 0;
318     }
319
320 #if defined(USE_MUTEX)
321     mutex_exit(&state->lock);
322     mutex_destroy(&state->lock);
323 #endif /* USE_MUTEX */
324
325     FREE(q->q_ptr, sizeof(ahdlc_state_t));
326     q->q_ptr         = NULL;
327     OTHERQ(q)->q_ptr = NULL;
328
329 #if defined(SUNOS4)
330     if (ppp_ahdlc_count)
331         ppp_ahdlc_count--;
332 #endif /* SUNOS4 */
333     
334     return 0;
335 }
336
337 /*
338  * Write side put routine
339  */
340 static int
341 ahdlc_wput(q, mp)
342     queue_t     *q;
343     mblk_t      *mp;
344 {
345     ahdlc_state_t       *state;
346     struct iocblk       *iop;
347     int                 error;
348     mblk_t              *np;
349     struct ppp_stats    *psp;
350
351     state = (ahdlc_state_t *) q->q_ptr;
352     if (state == 0) {
353         DPRINT("state == 0 in ahdlc_wput\n");
354         freemsg(mp);
355         return 0;
356     }
357
358     switch (mp->b_datap->db_type) {
359     case M_DATA:
360         /*
361          * A data packet - do character-stuffing and FCS, and
362          * send it onwards.
363          */
364         ahdlc_encode(q, mp);
365         freemsg(mp);
366         break;
367
368     case M_IOCTL:
369         iop = (struct iocblk *) mp->b_rptr;
370         error = EINVAL;
371         switch (iop->ioc_cmd) {
372         case PPPIO_XACCM:
373             if ((iop->ioc_count < sizeof(u_int32_t)) || 
374                 (iop->ioc_count > sizeof(ext_accm))) {
375                 break;
376             }
377             if (mp->b_cont == 0) {
378                 DPRINT1("ahdlc_wput/%d: PPPIO_XACCM b_cont = 0!\n", state->unit);
379                 break;
380             }
381 #if defined(USE_MUTEX)
382             mutex_enter(&state->lock);
383 #endif /* USE_MUTEX */
384             bcopy((caddr_t)mp->b_cont->b_rptr, (caddr_t)state->xaccm,
385                   iop->ioc_count);
386             state->xaccm[2] &= ~0x40000000;     /* don't escape 0x5e */
387             state->xaccm[3] |= 0x60000000;      /* do escape 0x7d, 0x7e */
388 #if defined(USE_MUTEX)
389             mutex_exit(&state->lock);
390 #endif /* USE_MUTEX */
391             iop->ioc_count = 0;
392             error = 0;
393             break;
394
395         case PPPIO_RACCM:
396             if (iop->ioc_count != sizeof(u_int32_t))
397                 break;
398             if (mp->b_cont == 0) {
399                 DPRINT1("ahdlc_wput/%d: PPPIO_RACCM b_cont = 0!\n", state->unit);
400                 break;
401             }
402 #if defined(USE_MUTEX)
403             mutex_enter(&state->lock);
404 #endif /* USE_MUTEX */
405             bcopy((caddr_t)mp->b_cont->b_rptr, (caddr_t)&state->raccm,
406                   sizeof(u_int32_t));
407 #if defined(USE_MUTEX)
408             mutex_exit(&state->lock);
409 #endif /* USE_MUTEX */
410             iop->ioc_count = 0;
411             error = 0;
412             break;
413
414         case PPPIO_GCLEAN:
415             np = allocb(sizeof(int), BPRI_HI);
416             if (np == 0) {
417                 error = ENOSR;
418                 break;
419             }
420             if (mp->b_cont != 0)
421                 freemsg(mp->b_cont);
422             mp->b_cont = np;
423 #if defined(USE_MUTEX)
424             mutex_enter(&state->lock);
425 #endif /* USE_MUTEX */
426             *(int *)np->b_wptr = state->flags & RCV_FLAGS;
427 #if defined(USE_MUTEX)
428             mutex_exit(&state->lock);
429 #endif /* USE_MUTEX */
430             np->b_wptr += sizeof(int);
431             iop->ioc_count = sizeof(int);
432             error = 0;
433             break;
434
435         case PPPIO_GETSTAT:
436             np = allocb(sizeof(struct ppp_stats), BPRI_HI);
437             if (np == 0) {
438                 error = ENOSR;
439                 break;
440             }
441             if (mp->b_cont != 0)
442                 freemsg(mp->b_cont);
443             mp->b_cont = np;
444             psp = (struct ppp_stats *) np->b_wptr;
445             np->b_wptr += sizeof(struct ppp_stats);
446             bzero((caddr_t)psp, sizeof(struct ppp_stats));
447             psp->p = state->stats;
448             iop->ioc_count = sizeof(struct ppp_stats);
449             error = 0;
450             break;
451
452         case PPPIO_LASTMOD:
453             /* we knew this anyway */
454             error = 0;
455             break;
456
457         default:
458             error = -1;
459             break;
460         }
461
462         if (error < 0)
463             putnext(q, mp);
464         else if (error == 0) {
465             mp->b_datap->db_type = M_IOCACK;
466             qreply(q, mp);
467         } else {
468             mp->b_datap->db_type = M_IOCNAK;
469             iop->ioc_count = 0;
470             iop->ioc_error = error;
471             qreply(q, mp);
472         }
473         break;
474
475     case M_CTL:
476         switch (*mp->b_rptr) {
477         case PPPCTL_MTU:
478 #if defined(USE_MUTEX)
479             mutex_enter(&state->lock);
480 #endif /* USE_MUTEX */
481             state->mtu = ((unsigned short *)mp->b_rptr)[1];
482 #if defined(USE_MUTEX)
483             mutex_exit(&state->lock);
484 #endif /* USE_MUTEX */
485             freemsg(mp);
486             break;
487         case PPPCTL_MRU:
488 #if defined(USE_MUTEX)
489             mutex_enter(&state->lock);
490 #endif /* USE_MUTEX */
491             state->mru = ((unsigned short *)mp->b_rptr)[1];
492 #if defined(USE_MUTEX)
493             mutex_exit(&state->lock);
494 #endif /* USE_MUTEX */
495             freemsg(mp);
496             break;
497         case PPPCTL_UNIT:
498 #if defined(USE_MUTEX)
499             mutex_enter(&state->lock);
500 #endif /* USE_MUTEX */
501             state->unit = mp->b_rptr[1];
502 #if defined(USE_MUTEX)
503             mutex_exit(&state->lock);
504 #endif /* USE_MUTEX */
505             break;
506         default:
507             putnext(q, mp);
508         }
509         break;
510
511     default:
512         putnext(q, mp);
513     }
514
515     return 0;
516 }
517
518 /*
519  * Read side put routine
520  */
521 static int
522 ahdlc_rput(q, mp)
523     queue_t *q;
524     mblk_t  *mp;
525 {
526     ahdlc_state_t *state;
527
528     state = (ahdlc_state_t *) q->q_ptr;
529     if (state == 0) {
530         DPRINT("state == 0 in ahdlc_rput\n");
531         freemsg(mp);
532         return 0;
533     }
534
535     switch (mp->b_datap->db_type) {
536     case M_DATA:
537         ahdlc_decode(q, mp);
538         break;
539
540     case M_HANGUP:
541 #if defined(USE_MUTEX)
542         mutex_enter(&state->lock);
543 #endif /* USE_MUTEX */
544         if (state->rx_buf != 0) {
545             /* XXX would like to send this up for debugging */
546             freemsg(state->rx_buf);
547             state->rx_buf = 0;
548         }
549         state->flags = IFLUSH;
550 #if defined(USE_MUTEX)
551         mutex_exit(&state->lock);
552 #endif /* USE_MUTEX */
553         putnext(q, mp);
554         break;
555
556     default:
557         putnext(q, mp);
558     }
559     return 0;
560 }
561
562 /*
563  * Extract bit c from map m, to determine if c needs to be escaped
564  */
565 #define IN_TX_MAP(c, m) ((m)[(c) >> 5] & (1 << ((c) & 0x1f)))
566
567 static void
568 ahdlc_encode(q, mp)
569     queue_t     *q;
570     mblk_t      *mp;
571 {
572     ahdlc_state_t       *state;
573     u_int32_t           *xaccm, loc_xaccm[8];
574     ushort_t            fcs;
575     size_t              outmp_len;
576     mblk_t              *outmp, *tmp;
577     uchar_t             *dp, fcs_val;
578     int                 is_lcp, code;
579 #if defined(SOL2)
580     clock_t             lbolt;
581 #endif /* SOL2 */
582
583     if (msgdsize(mp) < 4) {
584         return;
585     }
586
587     state = (ahdlc_state_t *)q->q_ptr;
588 #if defined(USE_MUTEX)
589     mutex_enter(&state->lock);
590 #endif /* USE_MUTEX */
591
592     /*
593      * Allocate an output buffer large enough to handle a case where all
594      * characters need to be escaped
595      */
596     outmp_len = (msgdsize(mp)    << 1) +                /* input block x 2 */
597                 (sizeof(fcs)     << 2) +                /* HDLC FCS x 4 */
598                 (sizeof(uchar_t) << 1);                 /* HDLC flags x 2 */
599
600     outmp = allocb(outmp_len, BPRI_MED);
601     if (outmp == NULL) {
602         state->stats.ppp_oerrors++;
603 #if defined(USE_MUTEX)
604         mutex_exit(&state->lock);
605 #endif /* USE_MUTEX */
606         putctl1(RD(q)->q_next, M_CTL, PPPCTL_OERROR);
607         return;
608     }
609
610 #if defined(SOL2)
611     /*
612      * Check if our last transmit happenned within flag_time, using
613      * the system's LBOLT value in clock ticks
614      */
615     if (drv_getparm(LBOLT, &lbolt) != -1) {
616         if (ABS((clock_t)lbolt - state->lbolt) > state->flag_time) {
617             *outmp->b_wptr++ = PPP_FLAG;
618         } 
619         state->lbolt = lbolt;
620     } else {
621         *outmp->b_wptr++ = PPP_FLAG;
622     }
623 #else
624     /*
625      * If the driver below still has a message to process, skip the
626      * HDLC flag, otherwise, put one in the beginning
627      */
628     if (qsize(q->q_next) == 0) {
629         *outmp->b_wptr++ = PPP_FLAG;
630     }
631 #endif
632
633     /*
634      * All control characters must be escaped for LCP packets with code
635      * values between 1 (Conf-Req) and 7 (Code-Rej).
636      */
637     is_lcp = ((MSG_BYTE(mp, 0) == PPP_ALLSTATIONS) && 
638               (MSG_BYTE(mp, 1) == PPP_UI) && 
639               (MSG_BYTE(mp, 2) == (PPP_LCP >> 8)) &&
640               (MSG_BYTE(mp, 3) == (PPP_LCP & 0xff)) &&
641               LCP_USE_DFLT(mp));
642
643     xaccm = state->xaccm;
644     if (is_lcp) {
645         bcopy((caddr_t)state->xaccm, (caddr_t)loc_xaccm, sizeof(loc_xaccm));
646         loc_xaccm[0] = ~0;      /* force escape on 0x00 through 0x1f */
647         xaccm = loc_xaccm;
648     }
649
650     fcs = PPP_INITFCS;          /* Initial FCS is 0xffff */
651
652     /*
653      * Process this block and the rest (if any) attached to the this one
654      */
655     for (tmp = mp; tmp; tmp = tmp->b_cont) {
656         if (tmp->b_datap->db_type == M_DATA) {
657             for (dp = tmp->b_rptr; dp < tmp->b_wptr; dp++) {
658                 fcs = PPP_FCS(fcs, *dp);
659                 if (IN_TX_MAP(*dp, xaccm)) {
660                     *outmp->b_wptr++ = PPP_ESCAPE;
661                     *outmp->b_wptr++ = *dp ^ PPP_TRANS;
662                 } else {
663                     *outmp->b_wptr++ = *dp;
664                 }
665             }
666         } else {
667             continue;   /* skip if db_type is something other than M_DATA */
668         }
669     }
670
671     /*
672      * Append the HDLC FCS, making sure that escaping is done on any
673      * necessary bytes
674      */
675     fcs_val = (fcs ^ 0xffff) & 0xff;
676     if (IN_TX_MAP(fcs_val, xaccm)) {
677         *outmp->b_wptr++ = PPP_ESCAPE;
678         *outmp->b_wptr++ = fcs_val ^ PPP_TRANS;
679     } else {
680         *outmp->b_wptr++ = fcs_val;
681     }
682
683     fcs_val = ((fcs ^ 0xffff) >> 8) & 0xff;
684     if (IN_TX_MAP(fcs_val, xaccm)) {
685         *outmp->b_wptr++ = PPP_ESCAPE;
686         *outmp->b_wptr++ = fcs_val ^ PPP_TRANS;
687     } else {
688         *outmp->b_wptr++ = fcs_val;
689     }
690
691     /*
692      * And finally, append the HDLC flag, and send it away
693      */
694     *outmp->b_wptr++ = PPP_FLAG;
695
696     state->stats.ppp_obytes += msgdsize(outmp);
697     state->stats.ppp_opackets++;
698
699 #if defined(USE_MUTEX)
700     mutex_exit(&state->lock);
701 #endif /* USE_MUTEX */
702
703     putnext(q, outmp);
704     return;
705 }
706
707 /*
708  * Checks the 32-bit receive ACCM to see if the byte needs un-escaping
709  */
710 #define IN_RX_MAP(c, m) ((((unsigned int) (uchar_t) (c)) < 0x20) && \
711                         (m) & (1 << (c)))
712
713
714 /*
715  * Process received characters.
716  */
717 static void
718 ahdlc_decode(q, mp)
719     queue_t *q;
720     mblk_t  *mp;
721 {
722     ahdlc_state_t   *state;
723     mblk_t          *om;
724     uchar_t         *dp;
725
726     state = (ahdlc_state_t *) q->q_ptr;
727
728 #if defined(USE_MUTEX)
729     mutex_enter(&state->lock);
730 #endif /* USE_MUTEX */
731
732     state->stats.ppp_ibytes += msgdsize(mp);
733
734     for (; mp != 0; om = mp->b_cont, freeb(mp), mp = om)
735     for (dp = mp->b_rptr; dp < mp->b_wptr; dp++) {
736
737         /*
738          * This should detect the lack of 8-bit communication channel
739          * which is necessary for PPP to work. In addition, it also
740          * checks on the parity.
741          */
742         if (*dp & 0x80)
743             state->flags |= RCV_B7_1;
744         else
745             state->flags |= RCV_B7_0;
746
747         if (paritytab[*dp >> 5] & (1 << (*dp & 0x1f)))
748             state->flags |= RCV_ODDP;
749         else
750             state->flags |= RCV_EVNP;
751
752         /*
753          * So we have a HDLC flag ...
754          */
755         if (*dp == PPP_FLAG) {
756
757             /*
758              * If we think that it marks the beginning of the frame,
759              * then continue to process the next octects
760              */
761             if ((state->flags & IFLUSH) ||
762                 (state->rx_buf == 0) ||
763                 (msgdsize(state->rx_buf) == 0)) {
764
765                 state->flags &= ~IFLUSH;
766                 continue;
767             }
768
769             /*
770              * We get here because the above condition isn't true,
771              * in which case the HDLC flag was there to mark the end
772              * of the frame (or so we think)
773              */
774             om = state->rx_buf;
775
776             if (state->infcs == PPP_GOODFCS) {
777                 state->stats.ppp_ipackets++;
778                 adjmsg(om, -PPP_FCSLEN);
779                 putnext(q, om);
780             } else {
781                 DPRINT2("ppp%d: bad fcs (len=%d)\n",
782                     state->unit, msgdsize(state->rx_buf));
783                 freemsg(state->rx_buf);
784                 state->flags &= ~(IFLUSH | ESCAPED);
785                 state->stats.ppp_ierrors++;
786                 putctl1(q->q_next, M_CTL, PPPCTL_IERROR);
787             }
788
789             state->rx_buf = 0;
790             continue;
791         }
792
793         if (state->flags & IFLUSH) {
794             continue;
795         }
796
797         /*
798          * Allocate a receive buffer, large enough to store a frame (after
799          * un-escaping) of at least 1500 octets. If MRU is negotiated to
800          * be more than the default, then allocate that much. In addition,
801          * we add an extra 32-bytes for a fudge factor
802          */ 
803         if (state->rx_buf == 0) {
804             state->rx_buf_size  = (state->mru < PPP_MRU ? PPP_MRU : state->mru);
805             state->rx_buf_size += (sizeof(u_int32_t) << 3);
806             state->rx_buf = allocb(state->rx_buf_size, BPRI_MED);
807
808             /*
809              * If allocation fails, try again on the next frame
810              */
811             if (state->rx_buf == 0) {
812                 state->flags |= IFLUSH;
813                 continue;
814             }
815             state->flags &= ~(IFLUSH | ESCAPED);
816             state->infcs  = PPP_INITFCS;
817         }
818
819         if (*dp == PPP_ESCAPE) {
820             state->flags |= ESCAPED;
821             continue;
822         }
823
824         /*
825          * Make sure we un-escape the necessary characters, as well as the
826          * ones in our receive async control character map
827          */
828         if (state->flags & ESCAPED) {
829             *dp ^= PPP_TRANS;
830             state->flags &= ~ESCAPED;
831         } else if (IN_RX_MAP(*dp, state->raccm)) 
832             continue;
833
834         /*
835          * Unless the peer lied to us about the negotiated MRU, we should
836          * never get a frame which is too long. If it happens, toss it away
837          * and grab the next incoming one
838          */
839         if (msgdsize(state->rx_buf) < state->rx_buf_size) {
840             state->infcs = PPP_FCS(state->infcs, *dp);
841             *state->rx_buf->b_wptr++ = *dp;
842         } else {
843             DPRINT2("ppp%d: frame too long (%d)\n",
844                 state->unit, msgdsize(state->rx_buf));
845             freemsg(state->rx_buf);
846             state->rx_buf     = 0;
847             state->flags     |= IFLUSH;
848         }
849     }
850
851 #if defined(USE_MUTEX)
852     mutex_exit(&state->lock);
853 #endif /* USE_MUTEX */
854 }
855
856 static int
857 msg_byte(mp, i)
858     mblk_t *mp;
859     unsigned int i;
860 {
861     while (mp != 0 && i >= mp->b_wptr - mp->b_rptr)
862         mp = mp->b_cont;
863     if (mp == 0)
864         return -1;
865     return mp->b_rptr[i];
866 }