10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * spppasyn.c - STREAMS module for doing PPP asynchronous HDLC.
30Sstevel@tonic-gate *
4*5640Scarlsonj * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
50Sstevel@tonic-gate * Use is subject to license terms.
60Sstevel@tonic-gate *
70Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software and its
80Sstevel@tonic-gate * documentation is hereby granted, provided that the above copyright
90Sstevel@tonic-gate * notice appears in all copies.
100Sstevel@tonic-gate *
110Sstevel@tonic-gate * SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF
120Sstevel@tonic-gate * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
130Sstevel@tonic-gate * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
140Sstevel@tonic-gate * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
150Sstevel@tonic-gate * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
160Sstevel@tonic-gate * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES
170Sstevel@tonic-gate *
180Sstevel@tonic-gate * Copyright (c) 1994 The Australian National University.
190Sstevel@tonic-gate * All rights reserved.
200Sstevel@tonic-gate *
210Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software and its
220Sstevel@tonic-gate * documentation is hereby granted, provided that the above copyright
230Sstevel@tonic-gate * notice appears in all copies. This software is provided without any
240Sstevel@tonic-gate * warranty, express or implied. The Australian National University
250Sstevel@tonic-gate * makes no representations about the suitability of this software for
260Sstevel@tonic-gate * any purpose.
270Sstevel@tonic-gate *
280Sstevel@tonic-gate * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
290Sstevel@tonic-gate * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
300Sstevel@tonic-gate * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
310Sstevel@tonic-gate * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY
320Sstevel@tonic-gate * OF SUCH DAMAGE.
330Sstevel@tonic-gate *
340Sstevel@tonic-gate * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
350Sstevel@tonic-gate * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
360Sstevel@tonic-gate * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
370Sstevel@tonic-gate * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
380Sstevel@tonic-gate * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
390Sstevel@tonic-gate * OR MODIFICATIONS.
400Sstevel@tonic-gate *
410Sstevel@tonic-gate * $Id: ppp_ahdlc.c,v 1.16 2000/03/06 19:38:12 masputra Exp $
420Sstevel@tonic-gate */
430Sstevel@tonic-gate
440Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
450Sstevel@tonic-gate
460Sstevel@tonic-gate #include <sys/types.h>
470Sstevel@tonic-gate #include <sys/param.h>
480Sstevel@tonic-gate #include <sys/stream.h>
490Sstevel@tonic-gate #include <sys/strsun.h>
500Sstevel@tonic-gate #include <sys/sysmacros.h>
510Sstevel@tonic-gate #include <sys/errno.h>
520Sstevel@tonic-gate #include <sys/conf.h>
530Sstevel@tonic-gate #include <sys/kmem.h>
540Sstevel@tonic-gate #include <sys/crc32.h>
550Sstevel@tonic-gate #include <sys/cmn_err.h>
560Sstevel@tonic-gate #include <sys/ddi.h>
570Sstevel@tonic-gate
580Sstevel@tonic-gate #include <net/ppp_defs.h>
590Sstevel@tonic-gate #include <net/pppio.h>
600Sstevel@tonic-gate
610Sstevel@tonic-gate #include "s_common.h"
620Sstevel@tonic-gate
630Sstevel@tonic-gate #ifdef DEBUG
640Sstevel@tonic-gate #define REPORT_CRC_TYPE
650Sstevel@tonic-gate #endif
660Sstevel@tonic-gate #include "spppasyn.h"
670Sstevel@tonic-gate
680Sstevel@tonic-gate /*
690Sstevel@tonic-gate * This is used to tag official Solaris sources. Please do not define
700Sstevel@tonic-gate * "INTERNAL_BUILD" when building this software outside of Sun
710Sstevel@tonic-gate * Microsystems.
720Sstevel@tonic-gate */
730Sstevel@tonic-gate #ifdef INTERNAL_BUILD
740Sstevel@tonic-gate /* MODINFO is limited to 32 characters. */
75*5640Scarlsonj const char spppasyn_module_description[] = "PPP 4.0 AHDLC";
760Sstevel@tonic-gate #else /* INTERNAL_BUILD */
770Sstevel@tonic-gate const char spppasyn_module_description[] = "ANU PPP AHDLC $Revision: 1.16$";
780Sstevel@tonic-gate
790Sstevel@tonic-gate /* LINTED */
800Sstevel@tonic-gate static const char buildtime[] = "Built " __DATE__ " at " __TIME__
810Sstevel@tonic-gate #ifdef DEBUG
820Sstevel@tonic-gate " DEBUG"
830Sstevel@tonic-gate #endif
840Sstevel@tonic-gate "\n";
850Sstevel@tonic-gate #endif /* INTERNAL_BUILD */
860Sstevel@tonic-gate
870Sstevel@tonic-gate static int spppasyn_open(queue_t *, dev_t *, int, int, cred_t *);
880Sstevel@tonic-gate static int spppasyn_close(queue_t *, int, cred_t *);
890Sstevel@tonic-gate static int spppasyn_wput(queue_t *, mblk_t *);
900Sstevel@tonic-gate static int spppasyn_rput(queue_t *, mblk_t *);
910Sstevel@tonic-gate static mblk_t *ahdlc_encode(queue_t *, mblk_t *);
920Sstevel@tonic-gate static mblk_t *ahdlc_decode(queue_t *, mblk_t *);
930Sstevel@tonic-gate static void spppasyn_timer(void *);
940Sstevel@tonic-gate static mblk_t *spppasyn_inpkt(queue_t *, mblk_t *);
950Sstevel@tonic-gate static mblk_t *spppasyn_muxencode(queue_t *, mblk_t *);
960Sstevel@tonic-gate
970Sstevel@tonic-gate #define RESET_MUX_VALUES(x) { \
980Sstevel@tonic-gate x->sa_mqhead = x->sa_mqtail = NULL; \
990Sstevel@tonic-gate x->sa_proto = 0; \
1000Sstevel@tonic-gate x->sa_mqlen = 0; \
1010Sstevel@tonic-gate }
1020Sstevel@tonic-gate #define IS_XMUX_ENABLED(x) \
1030Sstevel@tonic-gate ((x)->sa_flags & X_MUXMASK)
1040Sstevel@tonic-gate #define IS_RMUX_ENABLED(x) \
1050Sstevel@tonic-gate ((x)->sa_flags & R_MUXMASK)
1060Sstevel@tonic-gate #define IS_COMP_AC(x) \
1070Sstevel@tonic-gate ((x)->sa_flags & SAF_XCOMP_AC)
1080Sstevel@tonic-gate #define IS_COMP_PROT(x) \
1090Sstevel@tonic-gate ((x)->sa_flags & SAF_XCOMP_PROT)
1100Sstevel@tonic-gate #define IS_DECOMP_PROT(x) \
1110Sstevel@tonic-gate ((x)->sa_flags & SAF_RDECOMP_PROT)
1120Sstevel@tonic-gate
1130Sstevel@tonic-gate /*
1140Sstevel@tonic-gate * Don't send HDLC start flag if last transmit is within 1.5 seconds -
1150Sstevel@tonic-gate * FLAG_TIME is defined in nanoseconds.
1160Sstevel@tonic-gate */
1170Sstevel@tonic-gate #define FLAG_TIME 1500000000ul
1180Sstevel@tonic-gate
1190Sstevel@tonic-gate /*
1200Sstevel@tonic-gate * The usual AHDLC implementation enables the default escaping for all
1210Sstevel@tonic-gate * LCP frames. LCP_USE_DFLT() is used in this implementation to
1220Sstevel@tonic-gate * modify this rule slightly. If the code number happens to be
1230Sstevel@tonic-gate * Echo-Request, Echo-Reply, or Discard-Request (each of which may be
1240Sstevel@tonic-gate * sent only when LCP is in Opened state), then one may also use the
1250Sstevel@tonic-gate * negotiated ACCM; the RFC is silent on this. The theory is that
1260Sstevel@tonic-gate * pppd can construct Echo-Request messages that are guaranteed to
1270Sstevel@tonic-gate * fail if the negotiated ACCM is bad.
1280Sstevel@tonic-gate */
1290Sstevel@tonic-gate #define LCP_USE_DFLT(mp) ((code = MSG_BYTE((mp), 4)) < 9 || code > 11)
1300Sstevel@tonic-gate
1310Sstevel@tonic-gate /*
1320Sstevel@tonic-gate * Extract bit c from map m, to determine if character c needs to be
1330Sstevel@tonic-gate * escaped. Map 'm' is a pointer to a 256 bit map; 8 words of 32 bits
1340Sstevel@tonic-gate * each.
1350Sstevel@tonic-gate */
1360Sstevel@tonic-gate #define IN_TX_MAP(c, m) \
1370Sstevel@tonic-gate ((m)[(c) >> 5] & (1 << ((c) & 0x1f)))
1380Sstevel@tonic-gate
1390Sstevel@tonic-gate /*
1400Sstevel@tonic-gate * Checks the 32-bit receive ACCM to see if the byte should have been
1410Sstevel@tonic-gate * escaped by peer.
1420Sstevel@tonic-gate */
1430Sstevel@tonic-gate #define IN_RX_MAP(c, m) (((c) < 0x20) && ((m) & (1 << (c))))
1440Sstevel@tonic-gate
1450Sstevel@tonic-gate static struct module_info spppasyn_modinfo = {
1460Sstevel@tonic-gate AHDLC_MOD_ID, /* mi_idnum */
1470Sstevel@tonic-gate AHDLC_MOD_NAME, /* mi_idname */
1480Sstevel@tonic-gate 0, /* mi_minpsz */
1490Sstevel@tonic-gate INFPSZ, /* mi_maxpsz */
1500Sstevel@tonic-gate 0, /* mi_hiwat */
1510Sstevel@tonic-gate 0 /* mi_lowat */
1520Sstevel@tonic-gate };
1530Sstevel@tonic-gate
1540Sstevel@tonic-gate static struct qinit spppasyn_rinit = {
1550Sstevel@tonic-gate spppasyn_rput, /* qi_putp */
1560Sstevel@tonic-gate NULL, /* qi_srvp */
1570Sstevel@tonic-gate spppasyn_open, /* qi_qopen */
1580Sstevel@tonic-gate spppasyn_close, /* qi_qclose */
1590Sstevel@tonic-gate NULL, /* qi_qadmin */
1600Sstevel@tonic-gate &spppasyn_modinfo, /* qi_minfo */
1610Sstevel@tonic-gate NULL /* qi_mstat */
1620Sstevel@tonic-gate };
1630Sstevel@tonic-gate
1640Sstevel@tonic-gate static struct qinit spppasyn_winit = {
1650Sstevel@tonic-gate spppasyn_wput, /* qi_putp */
1660Sstevel@tonic-gate NULL, /* qi_srvp */
1670Sstevel@tonic-gate NULL, /* qi_qopen */
1680Sstevel@tonic-gate NULL, /* qi_qclose */
1690Sstevel@tonic-gate NULL, /* qi_qadmin */
1700Sstevel@tonic-gate &spppasyn_modinfo, /* qi_minfo */
1710Sstevel@tonic-gate NULL /* qi_mstat */
1720Sstevel@tonic-gate };
1730Sstevel@tonic-gate
1740Sstevel@tonic-gate struct streamtab spppasyn_tab = {
1750Sstevel@tonic-gate &spppasyn_rinit, /* st_rdinit */
1760Sstevel@tonic-gate &spppasyn_winit, /* st_wrinit */
1770Sstevel@tonic-gate NULL, /* st_muxrinit */
1780Sstevel@tonic-gate NULL, /* st_muxwinit */
1790Sstevel@tonic-gate };
1800Sstevel@tonic-gate
1810Sstevel@tonic-gate /* Matches above structure. */
1820Sstevel@tonic-gate static const char *kstat_names[] = {
1830Sstevel@tonic-gate "ioctls", "ioctlsfwd", "ioctlserr", "ctls",
1840Sstevel@tonic-gate "ctlsfwd", "ctlserr", "inbadchars", "inbadcharmask",
1850Sstevel@tonic-gate "inaborts", "inrunts", "inallocfails", "intoolongs",
1860Sstevel@tonic-gate "outrunts", "outallocfails", "incrcerrs", "unknownwrs",
1870Sstevel@tonic-gate "unknownrds", "hangups", "datain", "dataout",
1880Sstevel@tonic-gate "extrabufs", "sentmux", "recvmux", "inmuxerrs",
1890Sstevel@tonic-gate #ifdef REPORT_CRC_TYPE
1900Sstevel@tonic-gate "incrctype", "outcrctype",
1910Sstevel@tonic-gate #endif
1920Sstevel@tonic-gate };
1930Sstevel@tonic-gate
1940Sstevel@tonic-gate /* So. This is why we have optimizing compilers. */
1950Sstevel@tonic-gate #define KVAL(vn) state->sa_kstats.vn.value.ui32
1960Sstevel@tonic-gate #define KSET(vn, v) KVAL(vn) = (v)
1970Sstevel@tonic-gate #define KADD(vn, v) KSET(vn, KVAL(vn) + (v))
1980Sstevel@tonic-gate #define KOR(vn, v) KSET(vn, KVAL(vn) | (v))
1990Sstevel@tonic-gate #define KINCR(vn) KADD(vn, 1)
2000Sstevel@tonic-gate
2010Sstevel@tonic-gate static void ppp_dump_frame(sppp_ahdlc_t *state, mblk_t *mptr,
2020Sstevel@tonic-gate const char *msg);
2030Sstevel@tonic-gate
2040Sstevel@tonic-gate /*
2050Sstevel@tonic-gate * RCV_B7_1, etc., defined in net/pppio.h, are stored in flags also.
2060Sstevel@tonic-gate */
2070Sstevel@tonic-gate #define RCV_FLAGS (RCV_B7_1 | RCV_B7_0 | RCV_ODDP | RCV_EVNP)
2080Sstevel@tonic-gate
2090Sstevel@tonic-gate /*
2100Sstevel@tonic-gate * FCS lookup table as calculated by genfcstab.
2110Sstevel@tonic-gate */
2120Sstevel@tonic-gate static ushort_t fcstab[256] = {
2130Sstevel@tonic-gate 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
2140Sstevel@tonic-gate 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
2150Sstevel@tonic-gate 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
2160Sstevel@tonic-gate 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
2170Sstevel@tonic-gate 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
2180Sstevel@tonic-gate 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
2190Sstevel@tonic-gate 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
2200Sstevel@tonic-gate 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
2210Sstevel@tonic-gate 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
2220Sstevel@tonic-gate 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
2230Sstevel@tonic-gate 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
2240Sstevel@tonic-gate 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
2250Sstevel@tonic-gate 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
2260Sstevel@tonic-gate 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
2270Sstevel@tonic-gate 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
2280Sstevel@tonic-gate 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
2290Sstevel@tonic-gate 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
2300Sstevel@tonic-gate 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
2310Sstevel@tonic-gate 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
2320Sstevel@tonic-gate 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
2330Sstevel@tonic-gate 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
2340Sstevel@tonic-gate 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
2350Sstevel@tonic-gate 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
2360Sstevel@tonic-gate 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
2370Sstevel@tonic-gate 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
2380Sstevel@tonic-gate 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
2390Sstevel@tonic-gate 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
2400Sstevel@tonic-gate 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
2410Sstevel@tonic-gate 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
2420Sstevel@tonic-gate 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
2430Sstevel@tonic-gate 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
2440Sstevel@tonic-gate 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
2450Sstevel@tonic-gate };
2460Sstevel@tonic-gate
2470Sstevel@tonic-gate /*
2480Sstevel@tonic-gate * Per-character flags for accumulating input errors. Flags are
2490Sstevel@tonic-gate * accumulated for bit 7 set to 0, bit 7 set to 1, even parity
2500Sstevel@tonic-gate * characters, and odd parity characters. The link should see all
2510Sstevel@tonic-gate * four in the very first LCP Configure-Request if all is ok. (C0 is
2520Sstevel@tonic-gate * even parity and has bit 7 set to 1, and 23 is odd parity and has
2530Sstevel@tonic-gate * bit 7 set to 0.)
2540Sstevel@tonic-gate */
2550Sstevel@tonic-gate static uchar_t charflags[256] = {
2560Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP,
2570Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2580Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP,
2590Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP,
2600Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP,
2610Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2620Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2630Sstevel@tonic-gate RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2640Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP,
2650Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2660Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP,
2670Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP,
2680Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP,
2690Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP,
2700Sstevel@tonic-gate RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP,
2710Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP,
2720Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP,
2730Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2740Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP,
2750Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP,
2760Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP,
2770Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2780Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2790Sstevel@tonic-gate RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2800Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP,
2810Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2820Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2830Sstevel@tonic-gate RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2840Sstevel@tonic-gate RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_EVNP,
2850Sstevel@tonic-gate RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2860Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2870Sstevel@tonic-gate RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2880Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP,
2890Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2900Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP,
2910Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP,
2920Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP,
2930Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2940Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2950Sstevel@tonic-gate RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2960Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP,
2970Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2980Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_1|RCV_ODDP,
2990Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3000Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_ODDP,
3010Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3020Sstevel@tonic-gate RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3030Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3040Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_ODDP,
3050Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_EVNP,
3060Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_ODDP,
3070Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3080Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_ODDP,
3090Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3100Sstevel@tonic-gate RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3110Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3120Sstevel@tonic-gate RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_EVNP,
3130Sstevel@tonic-gate RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3140Sstevel@tonic-gate RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3150Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3160Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_ODDP,
3170Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3180Sstevel@tonic-gate RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3190Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3200Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_ODDP,
3210Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_EVNP,
3220Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_ODDP,
3230Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3240Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_ODDP,
3250Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_EVNP,
3260Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_EVNP,
3270Sstevel@tonic-gate RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_EVNP,
3280Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_ODDP,
3290Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_EVNP,
3300Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_ODDP,
3310Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3320Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_ODDP,
3330Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3340Sstevel@tonic-gate RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3350Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3360Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_ODDP,
3370Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_EVNP,
3380Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_ODDP,
3390Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3400Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_ODDP,
3410Sstevel@tonic-gate RCV_B7_1|RCV_EVNP
3420Sstevel@tonic-gate };
3430Sstevel@tonic-gate
3440Sstevel@tonic-gate /*
3450Sstevel@tonic-gate * Append two lists; preserve message boundaries.
3460Sstevel@tonic-gate * Warning: uses b_next.
3470Sstevel@tonic-gate */
3480Sstevel@tonic-gate static mblk_t *
sppp_mappend(mblk_t * m1,mblk_t * m2)3490Sstevel@tonic-gate sppp_mappend(mblk_t *m1, mblk_t *m2)
3500Sstevel@tonic-gate {
3510Sstevel@tonic-gate mblk_t *mret;
3520Sstevel@tonic-gate
3530Sstevel@tonic-gate if (m1 == NULL)
3540Sstevel@tonic-gate return (m2);
3550Sstevel@tonic-gate if (m2 == NULL)
3560Sstevel@tonic-gate return (m1);
3570Sstevel@tonic-gate
3580Sstevel@tonic-gate mret = m1;
3590Sstevel@tonic-gate while (m1->b_next != NULL)
3600Sstevel@tonic-gate m1 = m1->b_next;
3610Sstevel@tonic-gate m1->b_next = m2;
3620Sstevel@tonic-gate return (mret);
3630Sstevel@tonic-gate }
3640Sstevel@tonic-gate
3650Sstevel@tonic-gate /*
3660Sstevel@tonic-gate * Concatenate two mblk lists.
3670Sstevel@tonic-gate */
3680Sstevel@tonic-gate static mblk_t *
sppp_mcat(mblk_t * m1,mblk_t * m2)3690Sstevel@tonic-gate sppp_mcat(mblk_t *m1, mblk_t *m2)
3700Sstevel@tonic-gate {
3710Sstevel@tonic-gate mblk_t *mret;
3720Sstevel@tonic-gate
3730Sstevel@tonic-gate if (m1 == NULL)
3740Sstevel@tonic-gate return (m2);
3750Sstevel@tonic-gate if (m2 == NULL)
3760Sstevel@tonic-gate return (m1);
3770Sstevel@tonic-gate
3780Sstevel@tonic-gate mret = m1;
3790Sstevel@tonic-gate while (m1->b_cont != NULL)
3800Sstevel@tonic-gate m1 = m1->b_cont;
3810Sstevel@tonic-gate m1->b_cont = m2;
3820Sstevel@tonic-gate return (mret);
3830Sstevel@tonic-gate }
3840Sstevel@tonic-gate
3850Sstevel@tonic-gate /*
3860Sstevel@tonic-gate * spppasyn_open()
3870Sstevel@tonic-gate *
3880Sstevel@tonic-gate * STREAMS module open (entry) point. Called when spppasyn is pushed
3890Sstevel@tonic-gate * onto an asynchronous serial stream.
3900Sstevel@tonic-gate */
3910Sstevel@tonic-gate /* ARGSUSED */
3920Sstevel@tonic-gate static int
spppasyn_open(queue_t * q,dev_t * devp,int flag,int sflag,cred_t * credp)3930Sstevel@tonic-gate spppasyn_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp)
3940Sstevel@tonic-gate {
3950Sstevel@tonic-gate sppp_ahdlc_t *state;
3960Sstevel@tonic-gate
3970Sstevel@tonic-gate ASSERT(q != NULL);
3980Sstevel@tonic-gate
3990Sstevel@tonic-gate if (q->q_ptr != NULL) {
4000Sstevel@tonic-gate return (0); /* return if already opened */
4010Sstevel@tonic-gate }
4020Sstevel@tonic-gate
4030Sstevel@tonic-gate if (sflag != MODOPEN) {
4040Sstevel@tonic-gate return (EINVAL); /* only open as a module */
4050Sstevel@tonic-gate }
4060Sstevel@tonic-gate
4070Sstevel@tonic-gate state = (sppp_ahdlc_t *)kmem_zalloc(sizeof (sppp_ahdlc_t), KM_SLEEP);
4080Sstevel@tonic-gate ASSERT(state != NULL);
4090Sstevel@tonic-gate
4100Sstevel@tonic-gate q->q_ptr = (caddr_t)state;
4110Sstevel@tonic-gate WR(q)->q_ptr = (caddr_t)state;
4120Sstevel@tonic-gate
4130Sstevel@tonic-gate state->sa_xaccm[0] = 0xffffffff; /* escape 0x00 through 0x1f */
4140Sstevel@tonic-gate state->sa_xaccm[3] = 0x60000000; /* escape 0x7d and 0x7e */
4150Sstevel@tonic-gate state->sa_mru = PPP_MRU; /* default of 1500 bytes */
4160Sstevel@tonic-gate
4170Sstevel@tonic-gate qprocson(q);
4180Sstevel@tonic-gate
4190Sstevel@tonic-gate return (0);
4200Sstevel@tonic-gate }
4210Sstevel@tonic-gate
4220Sstevel@tonic-gate /*
4230Sstevel@tonic-gate * spppasyn_close()
4240Sstevel@tonic-gate *
4250Sstevel@tonic-gate * STREAMS module close (exit) point
4260Sstevel@tonic-gate */
4270Sstevel@tonic-gate /* ARGSUSED */
4280Sstevel@tonic-gate static int
spppasyn_close(queue_t * q,int flag,cred_t * credp)4290Sstevel@tonic-gate spppasyn_close(queue_t *q, int flag, cred_t *credp)
4300Sstevel@tonic-gate {
4310Sstevel@tonic-gate sppp_ahdlc_t *state;
4320Sstevel@tonic-gate
4330Sstevel@tonic-gate ASSERT(q != NULL);
4340Sstevel@tonic-gate state = (sppp_ahdlc_t *)q->q_ptr;
4350Sstevel@tonic-gate ASSERT(state != NULL);
4360Sstevel@tonic-gate
4370Sstevel@tonic-gate /* We're leaving now. No more calls, please. */
4380Sstevel@tonic-gate qprocsoff(q);
4390Sstevel@tonic-gate
4400Sstevel@tonic-gate if (state->sa_rx_buf != NULL) {
4410Sstevel@tonic-gate freemsg(state->sa_rx_buf);
4420Sstevel@tonic-gate state->sa_rx_buf = NULL;
4430Sstevel@tonic-gate }
4440Sstevel@tonic-gate
4450Sstevel@tonic-gate if (state->sa_ksp != NULL) {
4460Sstevel@tonic-gate kstat_delete(state->sa_ksp);
4470Sstevel@tonic-gate state->sa_ksp = NULL;
4480Sstevel@tonic-gate }
4490Sstevel@tonic-gate
4500Sstevel@tonic-gate if (state->sa_mqhead != NULL)
4510Sstevel@tonic-gate freemsg(state->sa_mqhead);
4520Sstevel@tonic-gate /* remove the time out routine */
4530Sstevel@tonic-gate if (state->sa_timeout_id != 0)
4540Sstevel@tonic-gate (void) quntimeout(q, state->sa_timeout_id);
4550Sstevel@tonic-gate
4560Sstevel@tonic-gate q->q_ptr = NULL;
4570Sstevel@tonic-gate WR(q)->q_ptr = NULL;
4580Sstevel@tonic-gate kmem_free(state, sizeof (sppp_ahdlc_t));
4590Sstevel@tonic-gate
4600Sstevel@tonic-gate return (0);
4610Sstevel@tonic-gate }
4620Sstevel@tonic-gate
4630Sstevel@tonic-gate /*
4640Sstevel@tonic-gate * Create the standard kernel statistics structure and attach it to
4650Sstevel@tonic-gate * the current state structure. This can be called only after
4660Sstevel@tonic-gate * assigning the unit number.
4670Sstevel@tonic-gate */
4680Sstevel@tonic-gate static void
create_kstats(sppp_ahdlc_t * state)4690Sstevel@tonic-gate create_kstats(sppp_ahdlc_t *state)
4700Sstevel@tonic-gate {
4710Sstevel@tonic-gate kstat_t *ksp;
4720Sstevel@tonic-gate char unitname[KSTAT_STRLEN];
4730Sstevel@tonic-gate int nstat, i;
4740Sstevel@tonic-gate kstat_named_t *knt;
4750Sstevel@tonic-gate
4760Sstevel@tonic-gate nstat = sizeof (state->sa_kstats) / sizeof (kstat_named_t);
4770Sstevel@tonic-gate knt = (kstat_named_t *)&state->sa_kstats;
4780Sstevel@tonic-gate for (i = 0; i < nstat; i++, knt++) {
4790Sstevel@tonic-gate #ifdef DEBUG
4800Sstevel@tonic-gate /* Just in case I do something silly here. */
4810Sstevel@tonic-gate if (i >= sizeof (kstat_names) / sizeof (kstat_names[0]))
4820Sstevel@tonic-gate (void) sprintf(knt->name, "unknown%d", i);
4830Sstevel@tonic-gate else
4840Sstevel@tonic-gate #endif
4850Sstevel@tonic-gate (void) strncpy(knt->name, kstat_names[i],
4860Sstevel@tonic-gate sizeof (knt->name));
4870Sstevel@tonic-gate knt->data_type = KSTAT_DATA_UINT32;
4880Sstevel@tonic-gate }
4890Sstevel@tonic-gate /*
4900Sstevel@tonic-gate * sprintf is known to be safe here because KSTAT_STRLEN is
4910Sstevel@tonic-gate * 31, the maximum module name length is 8, and the maximum
4920Sstevel@tonic-gate * string length from %d is 11. This was once snprintf, but
4930Sstevel@tonic-gate * that's not backward-compatible with Solaris 2.6.
4940Sstevel@tonic-gate */
495*5640Scarlsonj (void) sprintf(unitname, "%s" "%d", AHDLC_MOD_NAME, state->sa_unit);
4960Sstevel@tonic-gate ksp = kstat_create(AHDLC_MOD_NAME, state->sa_unit, unitname, "net",
4970Sstevel@tonic-gate KSTAT_TYPE_NAMED, nstat, KSTAT_FLAG_VIRTUAL);
4980Sstevel@tonic-gate if (ksp != NULL) {
4990Sstevel@tonic-gate ksp->ks_data = (void *)&state->sa_kstats;
5000Sstevel@tonic-gate kstat_install(ksp);
5010Sstevel@tonic-gate }
5020Sstevel@tonic-gate state->sa_ksp = ksp;
5030Sstevel@tonic-gate #ifdef REPORT_CRC_TYPE
5040Sstevel@tonic-gate KSET(pks_outcrctype, 16);
5050Sstevel@tonic-gate KSET(pks_incrctype, 16);
5060Sstevel@tonic-gate #endif
5070Sstevel@tonic-gate }
5080Sstevel@tonic-gate
5090Sstevel@tonic-gate /*
5100Sstevel@tonic-gate * spppasyn_inner_ioctl
5110Sstevel@tonic-gate *
5120Sstevel@tonic-gate * MT-Perimeters:
5130Sstevel@tonic-gate * exclusive inner
5140Sstevel@tonic-gate *
5150Sstevel@tonic-gate * Handle state-affecting ioctls.
5160Sstevel@tonic-gate */
5170Sstevel@tonic-gate static void
spppasyn_inner_ioctl(queue_t * q,mblk_t * mp)5180Sstevel@tonic-gate spppasyn_inner_ioctl(queue_t *q, mblk_t *mp)
5190Sstevel@tonic-gate {
5200Sstevel@tonic-gate sppp_ahdlc_t *state;
5210Sstevel@tonic-gate struct iocblk *iop;
5220Sstevel@tonic-gate int error;
5230Sstevel@tonic-gate int flagval;
5240Sstevel@tonic-gate int len;
5250Sstevel@tonic-gate uint32_t mux_flags;
5260Sstevel@tonic-gate uint32_t mask;
5270Sstevel@tonic-gate int flagmask;
5280Sstevel@tonic-gate
5290Sstevel@tonic-gate ASSERT(q != NULL && mp != NULL);
5300Sstevel@tonic-gate state = (sppp_ahdlc_t *)q->q_ptr;
5310Sstevel@tonic-gate iop = (struct iocblk *)mp->b_rptr;
5320Sstevel@tonic-gate ASSERT(state != NULL && iop != NULL);
5330Sstevel@tonic-gate
5340Sstevel@tonic-gate error = EINVAL;
5350Sstevel@tonic-gate len = 0;
5360Sstevel@tonic-gate
5370Sstevel@tonic-gate switch (iop->ioc_cmd) {
5380Sstevel@tonic-gate case PPPIO_XFCS:
5390Sstevel@tonic-gate /* Check for valid option length */
5400Sstevel@tonic-gate if (iop->ioc_count != sizeof (uint32_t) || mp->b_cont == NULL)
5410Sstevel@tonic-gate break;
5420Sstevel@tonic-gate
5430Sstevel@tonic-gate /* Grab flag value */
5440Sstevel@tonic-gate flagval = *(uint32_t *)mp->b_cont->b_rptr;
5450Sstevel@tonic-gate if (flagval < PPPFCS_16 || flagval > PPPFCS_NONE)
5460Sstevel@tonic-gate break;
5470Sstevel@tonic-gate state->sa_flags &= ~SAF_XMITCRC32 & ~SAF_XMITCRCNONE;
5480Sstevel@tonic-gate if (flagval == PPPFCS_32) {
5490Sstevel@tonic-gate #ifdef REPORT_CRC_TYPE
5500Sstevel@tonic-gate KSET(pks_outcrctype, 32);
5510Sstevel@tonic-gate #endif
5520Sstevel@tonic-gate state->sa_flags |= SAF_XMITCRC32;
5530Sstevel@tonic-gate } else if (flagval == PPPFCS_NONE) {
5540Sstevel@tonic-gate #ifdef REPORT_CRC_TYPE
5550Sstevel@tonic-gate KSET(pks_outcrctype, 0);
5560Sstevel@tonic-gate #endif
5570Sstevel@tonic-gate state->sa_flags |= SAF_XMITCRCNONE;
5580Sstevel@tonic-gate }
5590Sstevel@tonic-gate #ifdef REPORT_CRC_TYPE
5600Sstevel@tonic-gate else {
5610Sstevel@tonic-gate KSET(pks_outcrctype, 16);
5620Sstevel@tonic-gate }
5630Sstevel@tonic-gate #endif
5640Sstevel@tonic-gate
5650Sstevel@tonic-gate /* Return success */
5660Sstevel@tonic-gate error = 0;
5670Sstevel@tonic-gate break;
5680Sstevel@tonic-gate
5690Sstevel@tonic-gate case PPPIO_RFCS:
5700Sstevel@tonic-gate /* Check for valid option length */
5710Sstevel@tonic-gate if (iop->ioc_count != sizeof (uint32_t) || mp->b_cont == NULL)
5720Sstevel@tonic-gate break;
5730Sstevel@tonic-gate
5740Sstevel@tonic-gate /* Grab flag value */
5750Sstevel@tonic-gate flagval = *(uint32_t *)mp->b_cont->b_rptr;
5760Sstevel@tonic-gate if (flagval < PPPFCS_16 || flagval > PPPFCS_NONE)
5770Sstevel@tonic-gate break;
5780Sstevel@tonic-gate state->sa_flags &= ~SAF_RECVCRC32 & ~SAF_RECVCRCNONE;
5790Sstevel@tonic-gate if (flagval == PPPFCS_32) {
5800Sstevel@tonic-gate #ifdef REPORT_CRC_TYPE
5810Sstevel@tonic-gate KSET(pks_incrctype, 32);
5820Sstevel@tonic-gate #endif
5830Sstevel@tonic-gate state->sa_flags |= SAF_RECVCRC32;
5840Sstevel@tonic-gate } else if (flagval == PPPFCS_NONE) {
5850Sstevel@tonic-gate #ifdef REPORT_CRC_TYPE
5860Sstevel@tonic-gate KSET(pks_incrctype, 0);
5870Sstevel@tonic-gate #endif
5880Sstevel@tonic-gate state->sa_flags |= SAF_RECVCRCNONE;
5890Sstevel@tonic-gate }
5900Sstevel@tonic-gate #ifdef REPORT_CRC_TYPE
5910Sstevel@tonic-gate else {
5920Sstevel@tonic-gate KSET(pks_incrctype, 16);
5930Sstevel@tonic-gate }
5940Sstevel@tonic-gate #endif
5950Sstevel@tonic-gate
5960Sstevel@tonic-gate /* Return success */
5970Sstevel@tonic-gate error = 0;
5980Sstevel@tonic-gate break;
5990Sstevel@tonic-gate
6000Sstevel@tonic-gate case PPPIO_XACCM:
6010Sstevel@tonic-gate /* Check for valid asyncmap length */
6020Sstevel@tonic-gate if (iop->ioc_count < sizeof (uint32_t) ||
6030Sstevel@tonic-gate iop->ioc_count > sizeof (ext_accm) ||
6040Sstevel@tonic-gate mp->b_cont == NULL)
6050Sstevel@tonic-gate break;
6060Sstevel@tonic-gate
6070Sstevel@tonic-gate /* Copy user's asyncmap into our state structure. */
6080Sstevel@tonic-gate bcopy((caddr_t)mp->b_cont->b_rptr,
6090Sstevel@tonic-gate (caddr_t)state->sa_xaccm, iop->ioc_count);
6100Sstevel@tonic-gate
6110Sstevel@tonic-gate state->sa_xaccm[2] &= ~0x40000000; /* don't escape 0x5e */
6120Sstevel@tonic-gate state->sa_xaccm[3] |= 0x60000000; /* escape 0x7d, 0x7e */
6130Sstevel@tonic-gate
6140Sstevel@tonic-gate error = 0;
6150Sstevel@tonic-gate break;
6160Sstevel@tonic-gate
6170Sstevel@tonic-gate case PPPIO_RACCM:
6180Sstevel@tonic-gate /* Check for valid asyncmap length (only ctrl chars) */
6190Sstevel@tonic-gate if (iop->ioc_count != sizeof (uint32_t) ||
6200Sstevel@tonic-gate mp->b_cont == NULL)
6210Sstevel@tonic-gate break;
6220Sstevel@tonic-gate
6230Sstevel@tonic-gate state->sa_raccm = *(uint32_t *)mp->b_cont->b_rptr;
6240Sstevel@tonic-gate
6250Sstevel@tonic-gate error = 0;
6260Sstevel@tonic-gate break;
6270Sstevel@tonic-gate
6280Sstevel@tonic-gate case PPPIO_LASTMOD:
6290Sstevel@tonic-gate /* We already know this. */
6300Sstevel@tonic-gate state->sa_flags |= SAF_LASTMOD;
6310Sstevel@tonic-gate error = 0;
6320Sstevel@tonic-gate break;
6330Sstevel@tonic-gate
6340Sstevel@tonic-gate case PPPIO_MUX:
6350Sstevel@tonic-gate /* set the compression flags */
6360Sstevel@tonic-gate if (iop->ioc_count != 2 * sizeof (uint32_t) ||
6370Sstevel@tonic-gate mp->b_cont == NULL)
6380Sstevel@tonic-gate break;
6390Sstevel@tonic-gate
6400Sstevel@tonic-gate /* set the mux flags */
6410Sstevel@tonic-gate mux_flags = ((uint32_t *)mp->b_cont->b_rptr)[0];
6420Sstevel@tonic-gate mask = ((uint32_t *)mp->b_cont->b_rptr)[1];
6430Sstevel@tonic-gate if (mux_flags != 0)
6440Sstevel@tonic-gate state->sa_flags = (state->sa_flags & ~mask) | (mask);
6450Sstevel@tonic-gate
6460Sstevel@tonic-gate /* set the multiplexing timer value */
6470Sstevel@tonic-gate if (mask & R_MUXMASK)
6480Sstevel@tonic-gate state->sa_timeout_usec = mux_flags;
6490Sstevel@tonic-gate
6500Sstevel@tonic-gate error = 0;
6510Sstevel@tonic-gate break;
6520Sstevel@tonic-gate
6530Sstevel@tonic-gate case PPPIO_CFLAGS:
6540Sstevel@tonic-gate if (iop->ioc_count != 2 * sizeof (uint32_t) ||
6550Sstevel@tonic-gate mp->b_cont == NULL)
6560Sstevel@tonic-gate break;
6570Sstevel@tonic-gate
6580Sstevel@tonic-gate flagval = (((uint32_t *)mp->b_cont->b_rptr)[0] << 20) &
6590Sstevel@tonic-gate (SAF_RDECOMP_PROT | SAF_RDECOMP_AC | SAF_XCOMP_PROT |
660*5640Scarlsonj SAF_XCOMP_AC);
6610Sstevel@tonic-gate flagmask = (((uint32_t *)mp->b_cont->b_rptr)[1] << 20) &
6620Sstevel@tonic-gate (SAF_RDECOMP_PROT | SAF_RDECOMP_AC | SAF_XCOMP_PROT |
663*5640Scarlsonj SAF_XCOMP_AC);
6640Sstevel@tonic-gate state->sa_flags = flagval | (state->sa_flags & ~flagmask);
6650Sstevel@tonic-gate *(uint32_t *)mp->b_cont->b_rptr = state->sa_flags >> 20;
6660Sstevel@tonic-gate len = sizeof (uint32_t);
6670Sstevel@tonic-gate error = 0;
6680Sstevel@tonic-gate break;
6690Sstevel@tonic-gate
6700Sstevel@tonic-gate case PPPIO_DEBUG:
6710Sstevel@tonic-gate if (iop->ioc_count != sizeof (uint32_t) || mp->b_cont == NULL)
6720Sstevel@tonic-gate break;
6730Sstevel@tonic-gate
6740Sstevel@tonic-gate flagval = *(uint32_t *)mp->b_cont->b_rptr;
6750Sstevel@tonic-gate if (flagval != PPPDBG_LOG + PPPDBG_AHDLC) {
6760Sstevel@tonic-gate putnext(q, mp);
6770Sstevel@tonic-gate return;
6780Sstevel@tonic-gate }
6790Sstevel@tonic-gate cmn_err(CE_CONT, AHDLC_MOD_NAME "%d: debug log enabled\n",
6800Sstevel@tonic-gate state->sa_unit);
6810Sstevel@tonic-gate state->sa_flags |= SAF_XMITDUMP | SAF_RECVDUMP;
6820Sstevel@tonic-gate error = 0;
6830Sstevel@tonic-gate break;
6840Sstevel@tonic-gate }
6850Sstevel@tonic-gate
6860Sstevel@tonic-gate if (error == 0) {
6870Sstevel@tonic-gate /* Success; tell the user */
6880Sstevel@tonic-gate if (mp->b_cont == NULL)
6890Sstevel@tonic-gate len = 0;
6900Sstevel@tonic-gate else
6910Sstevel@tonic-gate mp->b_cont->b_wptr = mp->b_cont->b_rptr + len;
6920Sstevel@tonic-gate miocack(q, mp, len, 0);
6930Sstevel@tonic-gate } else {
6940Sstevel@tonic-gate /* Failure; send error back upstream. */
6950Sstevel@tonic-gate KINCR(pks_ioctlserr);
6960Sstevel@tonic-gate miocnak(q, mp, 0, error);
6970Sstevel@tonic-gate }
6980Sstevel@tonic-gate }
6990Sstevel@tonic-gate
7000Sstevel@tonic-gate /*
7010Sstevel@tonic-gate * spppasyn_inner_mctl
7020Sstevel@tonic-gate *
7030Sstevel@tonic-gate * MT-Perimeters:
7040Sstevel@tonic-gate * exclusive inner
7050Sstevel@tonic-gate *
7060Sstevel@tonic-gate * Handle state-affecting M_CTL messages.
7070Sstevel@tonic-gate */
7080Sstevel@tonic-gate static void
spppasyn_inner_mctl(queue_t * q,mblk_t * mp)7090Sstevel@tonic-gate spppasyn_inner_mctl(queue_t *q, mblk_t *mp)
7100Sstevel@tonic-gate {
7110Sstevel@tonic-gate sppp_ahdlc_t *state;
7120Sstevel@tonic-gate int msglen;
7130Sstevel@tonic-gate int error;
7140Sstevel@tonic-gate
7150Sstevel@tonic-gate ASSERT(q != NULL && mp != NULL);
7160Sstevel@tonic-gate state = (sppp_ahdlc_t *)q->q_ptr;
7170Sstevel@tonic-gate ASSERT(state != NULL);
7180Sstevel@tonic-gate
7190Sstevel@tonic-gate msglen = MBLKL(mp);
7200Sstevel@tonic-gate error = 0;
7210Sstevel@tonic-gate switch (*mp->b_rptr) {
7220Sstevel@tonic-gate case PPPCTL_MTU:
7230Sstevel@tonic-gate /* Just ignore the MTU */
7240Sstevel@tonic-gate break;
7250Sstevel@tonic-gate
7260Sstevel@tonic-gate case PPPCTL_MRU:
7270Sstevel@tonic-gate if (msglen != 4)
7280Sstevel@tonic-gate error = EINVAL;
7290Sstevel@tonic-gate else
7300Sstevel@tonic-gate state->sa_mru =
7310Sstevel@tonic-gate ((ushort_t *)mp->b_rptr)[1];
7320Sstevel@tonic-gate break;
7330Sstevel@tonic-gate
7340Sstevel@tonic-gate case PPPCTL_UNIT:
7350Sstevel@tonic-gate if (state->sa_ksp != NULL) {
7360Sstevel@tonic-gate error = EINVAL;
7370Sstevel@tonic-gate break;
7380Sstevel@tonic-gate }
7390Sstevel@tonic-gate if (msglen == 2)
7400Sstevel@tonic-gate state->sa_unit = mp->b_rptr[1];
7410Sstevel@tonic-gate else if (msglen == 8)
7420Sstevel@tonic-gate state->sa_unit =
7430Sstevel@tonic-gate ((uint32_t *)mp->b_rptr)[1];
7440Sstevel@tonic-gate else
7450Sstevel@tonic-gate error = EINVAL;
7460Sstevel@tonic-gate if (error == 0 && state->sa_ksp == NULL)
7470Sstevel@tonic-gate create_kstats(state);
7480Sstevel@tonic-gate break;
7490Sstevel@tonic-gate }
7500Sstevel@tonic-gate
7510Sstevel@tonic-gate if (error > 0) {
7520Sstevel@tonic-gate KINCR(pks_ctlserr);
7530Sstevel@tonic-gate }
7540Sstevel@tonic-gate if (state->sa_flags & SAF_LASTMOD) {
7550Sstevel@tonic-gate freemsg(mp);
7560Sstevel@tonic-gate } else {
7570Sstevel@tonic-gate KINCR(pks_ctlsfwd);
7580Sstevel@tonic-gate putnext(q, mp);
7590Sstevel@tonic-gate }
7600Sstevel@tonic-gate }
7610Sstevel@tonic-gate
7620Sstevel@tonic-gate /*
7630Sstevel@tonic-gate * spppasyn_wput()
7640Sstevel@tonic-gate *
7650Sstevel@tonic-gate * MT-Perimeters:
7660Sstevel@tonic-gate * exclusive inner.
7670Sstevel@tonic-gate *
7680Sstevel@tonic-gate * Write side put routine. This called by the modules above us (likely to
7690Sstevel@tonic-gate * be the compression module) to transmit data or pass along ioctls.
7700Sstevel@tonic-gate */
7710Sstevel@tonic-gate static int
spppasyn_wput(queue_t * q,mblk_t * mp)7720Sstevel@tonic-gate spppasyn_wput(queue_t *q, mblk_t *mp)
7730Sstevel@tonic-gate {
7740Sstevel@tonic-gate sppp_ahdlc_t *state;
7750Sstevel@tonic-gate struct iocblk *iop;
7760Sstevel@tonic-gate int error;
7770Sstevel@tonic-gate mblk_t *np;
7780Sstevel@tonic-gate struct ppp_stats64 *psp;
7790Sstevel@tonic-gate int msglen;
7800Sstevel@tonic-gate
7810Sstevel@tonic-gate ASSERT(q != NULL && mp != NULL);
7820Sstevel@tonic-gate state = (sppp_ahdlc_t *)q->q_ptr;
7830Sstevel@tonic-gate ASSERT(state != NULL);
7840Sstevel@tonic-gate
7850Sstevel@tonic-gate switch (MTYPE(mp)) {
7860Sstevel@tonic-gate
7870Sstevel@tonic-gate case M_DATA:
7880Sstevel@tonic-gate /*
7890Sstevel@tonic-gate * A data packet - do character-stuffing and FCS, and
7900Sstevel@tonic-gate * send it onwards. The blocks are freed as we go.
7910Sstevel@tonic-gate */
7920Sstevel@tonic-gate if (IS_XMUX_ENABLED(state))
7930Sstevel@tonic-gate mp = spppasyn_muxencode(q, mp);
7940Sstevel@tonic-gate else
7950Sstevel@tonic-gate mp = ahdlc_encode(q, mp);
7960Sstevel@tonic-gate if (mp != NULL)
7970Sstevel@tonic-gate putnext(q, mp);
7980Sstevel@tonic-gate break;
7990Sstevel@tonic-gate
8000Sstevel@tonic-gate case M_IOCTL:
8010Sstevel@tonic-gate
8020Sstevel@tonic-gate KINCR(pks_ioctls);
8030Sstevel@tonic-gate iop = (struct iocblk *)mp->b_rptr;
8040Sstevel@tonic-gate
8050Sstevel@tonic-gate msglen = 0;
8060Sstevel@tonic-gate
8070Sstevel@tonic-gate switch (iop->ioc_cmd) {
8080Sstevel@tonic-gate case PPPIO_XFCS:
8090Sstevel@tonic-gate case PPPIO_RFCS:
8100Sstevel@tonic-gate case PPPIO_XACCM:
8110Sstevel@tonic-gate case PPPIO_RACCM:
8120Sstevel@tonic-gate case PPPIO_LASTMOD:
8130Sstevel@tonic-gate case PPPIO_DEBUG:
8140Sstevel@tonic-gate case PPPIO_MUX:
8150Sstevel@tonic-gate case PPPIO_CFLAGS:
8160Sstevel@tonic-gate spppasyn_inner_ioctl(q, mp);
8170Sstevel@tonic-gate return (0);
8180Sstevel@tonic-gate
8190Sstevel@tonic-gate case PPPIO_GCLEAN:
8200Sstevel@tonic-gate np = allocb(sizeof (uint32_t), BPRI_HI);
8210Sstevel@tonic-gate if (np == NULL) {
8220Sstevel@tonic-gate error = ENOSR;
8230Sstevel@tonic-gate break;
8240Sstevel@tonic-gate }
8250Sstevel@tonic-gate if (mp->b_cont != NULL) {
8260Sstevel@tonic-gate freemsg(mp->b_cont);
8270Sstevel@tonic-gate }
8280Sstevel@tonic-gate mp->b_cont = np;
8290Sstevel@tonic-gate
8300Sstevel@tonic-gate *(uint32_t *)np->b_wptr = state->sa_flags & RCV_FLAGS;
8310Sstevel@tonic-gate
8320Sstevel@tonic-gate msglen = sizeof (uint32_t);
8330Sstevel@tonic-gate np->b_wptr += msglen;
8340Sstevel@tonic-gate error = 0;
8350Sstevel@tonic-gate break;
8360Sstevel@tonic-gate
8370Sstevel@tonic-gate case PPPIO_GETSTAT:
8380Sstevel@tonic-gate error = EINVAL;
8390Sstevel@tonic-gate break;
8400Sstevel@tonic-gate
8410Sstevel@tonic-gate case PPPIO_GETSTAT64:
8420Sstevel@tonic-gate np = allocb(sizeof (*psp), BPRI_HI);
8430Sstevel@tonic-gate if (np == NULL) {
8440Sstevel@tonic-gate error = ENOSR;
8450Sstevel@tonic-gate break;
8460Sstevel@tonic-gate }
8470Sstevel@tonic-gate if (mp->b_cont != NULL) {
8480Sstevel@tonic-gate freemsg(mp->b_cont);
8490Sstevel@tonic-gate }
8500Sstevel@tonic-gate mp->b_cont = np;
8510Sstevel@tonic-gate
8520Sstevel@tonic-gate psp = (struct ppp_stats64 *)np->b_wptr;
8530Sstevel@tonic-gate bzero((caddr_t)psp, sizeof (*psp));
8540Sstevel@tonic-gate psp->p = state->sa_stats;
8550Sstevel@tonic-gate
8560Sstevel@tonic-gate msglen = sizeof (*psp);
8570Sstevel@tonic-gate np->b_wptr += msglen;
8580Sstevel@tonic-gate error = 0;
8590Sstevel@tonic-gate break;
8600Sstevel@tonic-gate
8610Sstevel@tonic-gate case PPPIO_GTYPE:
8620Sstevel@tonic-gate np = allocb(sizeof (uint32_t), BPRI_HI);
8630Sstevel@tonic-gate if (np == NULL) {
8640Sstevel@tonic-gate error = ENOSR;
8650Sstevel@tonic-gate break;
8660Sstevel@tonic-gate }
8670Sstevel@tonic-gate if (mp->b_cont != NULL) {
8680Sstevel@tonic-gate freemsg(mp->b_cont);
8690Sstevel@tonic-gate }
8700Sstevel@tonic-gate mp->b_cont = np;
8710Sstevel@tonic-gate
8720Sstevel@tonic-gate *(uint32_t *)np->b_wptr = PPPTYP_AHDLC;
8730Sstevel@tonic-gate
8740Sstevel@tonic-gate msglen = sizeof (uint32_t);
8750Sstevel@tonic-gate np->b_wptr += msglen;
8760Sstevel@tonic-gate error = 0;
8770Sstevel@tonic-gate break;
8780Sstevel@tonic-gate
8790Sstevel@tonic-gate default:
8800Sstevel@tonic-gate /* Unknown ioctl -- forward along */
8810Sstevel@tonic-gate KINCR(pks_ioctlsfwd);
8820Sstevel@tonic-gate putnext(q, mp);
8830Sstevel@tonic-gate return (0);
8840Sstevel@tonic-gate }
8850Sstevel@tonic-gate
8860Sstevel@tonic-gate if (error == 0) {
8870Sstevel@tonic-gate /* Success; tell the user */
8880Sstevel@tonic-gate miocack(q, mp, msglen, 0);
8890Sstevel@tonic-gate } else {
8900Sstevel@tonic-gate /* Failure; send error back upstream. */
8910Sstevel@tonic-gate KINCR(pks_ioctlserr);
8920Sstevel@tonic-gate miocnak(q, mp, 0, error);
8930Sstevel@tonic-gate }
8940Sstevel@tonic-gate
8950Sstevel@tonic-gate break;
8960Sstevel@tonic-gate
8970Sstevel@tonic-gate case M_CTL:
8980Sstevel@tonic-gate KINCR(pks_ctls);
8990Sstevel@tonic-gate spppasyn_inner_mctl(q, mp);
9000Sstevel@tonic-gate break;
9010Sstevel@tonic-gate
9020Sstevel@tonic-gate default:
9030Sstevel@tonic-gate if (state->sa_flags & (SAF_XMITDUMP|SAF_RECVDUMP))
9040Sstevel@tonic-gate cmn_err(CE_CONT,
9050Sstevel@tonic-gate "spppasyn_wpur: unknown buffer type %d",
9060Sstevel@tonic-gate MTYPE(mp));
9070Sstevel@tonic-gate KINCR(pks_unknownwrs);
9080Sstevel@tonic-gate putnext(q, mp);
9090Sstevel@tonic-gate break;
9100Sstevel@tonic-gate }
9110Sstevel@tonic-gate
9120Sstevel@tonic-gate return (0);
9130Sstevel@tonic-gate }
9140Sstevel@tonic-gate
9150Sstevel@tonic-gate /*
9160Sstevel@tonic-gate * spppasyn_rput()
9170Sstevel@tonic-gate *
9180Sstevel@tonic-gate * MT-Perimeters:
9190Sstevel@tonic-gate * exclusive inner.
9200Sstevel@tonic-gate *
9210Sstevel@tonic-gate * Read side put routine. This is called by the async serial driver
9220Sstevel@tonic-gate * below us to handle received data and returned signals (like
9230Sstevel@tonic-gate * hang-up).
9240Sstevel@tonic-gate */
9250Sstevel@tonic-gate static int
spppasyn_rput(queue_t * q,mblk_t * mp)9260Sstevel@tonic-gate spppasyn_rput(queue_t *q, mblk_t *mp)
9270Sstevel@tonic-gate {
9280Sstevel@tonic-gate sppp_ahdlc_t *state;
9290Sstevel@tonic-gate mblk_t *mpnext;
9300Sstevel@tonic-gate
9310Sstevel@tonic-gate ASSERT(q != NULL && mp != NULL);
9320Sstevel@tonic-gate state = (sppp_ahdlc_t *)q->q_ptr;
9330Sstevel@tonic-gate ASSERT(state != NULL);
9340Sstevel@tonic-gate
9350Sstevel@tonic-gate switch (MTYPE(mp)) {
9360Sstevel@tonic-gate
9370Sstevel@tonic-gate case M_DATA:
9380Sstevel@tonic-gate /* Note -- decoder frees the buffers */
9390Sstevel@tonic-gate mp = ahdlc_decode(q, mp);
9400Sstevel@tonic-gate while (mp != NULL) {
9410Sstevel@tonic-gate mpnext = mp->b_next;
9420Sstevel@tonic-gate mp->b_next = NULL;
9430Sstevel@tonic-gate putnext(q, mp);
9440Sstevel@tonic-gate mp = mpnext;
9450Sstevel@tonic-gate }
9460Sstevel@tonic-gate break;
9470Sstevel@tonic-gate
9480Sstevel@tonic-gate case M_HANGUP:
9490Sstevel@tonic-gate KINCR(pks_hangups);
9500Sstevel@tonic-gate state->sa_flags |= SAF_IFLUSH;
9510Sstevel@tonic-gate putnext(q, mp);
9520Sstevel@tonic-gate break;
9530Sstevel@tonic-gate
9540Sstevel@tonic-gate default:
9550Sstevel@tonic-gate if (state->sa_flags & (SAF_XMITDUMP|SAF_RECVDUMP)) {
9560Sstevel@tonic-gate if (MTYPE(mp) == M_IOCTL)
9570Sstevel@tonic-gate cmn_err(CE_CONT,
9580Sstevel@tonic-gate "spppasyn_rput: unexpected ioctl %X",
9590Sstevel@tonic-gate ((struct iocblk *)mp->b_rptr)->ioc_cmd);
9600Sstevel@tonic-gate else
9610Sstevel@tonic-gate cmn_err(CE_CONT,
9620Sstevel@tonic-gate "spppasyn_rput: unknown buffer type %d",
9630Sstevel@tonic-gate MTYPE(mp));
9640Sstevel@tonic-gate }
9650Sstevel@tonic-gate KINCR(pks_unknownrds);
9660Sstevel@tonic-gate putnext(q, mp);
9670Sstevel@tonic-gate break;
9680Sstevel@tonic-gate }
9690Sstevel@tonic-gate
9700Sstevel@tonic-gate return (0);
9710Sstevel@tonic-gate }
9720Sstevel@tonic-gate
9730Sstevel@tonic-gate /*
9740Sstevel@tonic-gate * ahdlc_encode
9750Sstevel@tonic-gate *
9760Sstevel@tonic-gate * Perform asynchronous HDLC framing on a given buffer and transmit
9770Sstevel@tonic-gate * the result. The state structure must be valid. The input buffers
9780Sstevel@tonic-gate * are freed as we go.
9790Sstevel@tonic-gate *
9800Sstevel@tonic-gate * This function is called by wput and just encodes the data. Wput
9810Sstevel@tonic-gate * then calls putnext directly. There's no service routine for this
9820Sstevel@tonic-gate * module, so flow control is asserted by the module below us up to
9830Sstevel@tonic-gate * our caller by the STREAMS framework. This is by design -- this
9840Sstevel@tonic-gate * module does not queue anything so that other modules can make QoS
9850Sstevel@tonic-gate * decisions.
9860Sstevel@tonic-gate */
9870Sstevel@tonic-gate static mblk_t *
ahdlc_encode(queue_t * q,mblk_t * mp)9880Sstevel@tonic-gate ahdlc_encode(queue_t *q, mblk_t *mp)
9890Sstevel@tonic-gate {
9900Sstevel@tonic-gate sppp_ahdlc_t *state;
9910Sstevel@tonic-gate uint32_t loc_xaccm[8];
9920Sstevel@tonic-gate ushort_t fcs16;
9930Sstevel@tonic-gate uint32_t fcs32;
9940Sstevel@tonic-gate size_t msglen;
9950Sstevel@tonic-gate size_t outmp_len;
9960Sstevel@tonic-gate mblk_t *outmp;
9970Sstevel@tonic-gate mblk_t *curout;
9980Sstevel@tonic-gate mblk_t *tmp;
9990Sstevel@tonic-gate uchar_t *ep;
10000Sstevel@tonic-gate uchar_t *dp;
10010Sstevel@tonic-gate uchar_t *tp;
10020Sstevel@tonic-gate uchar_t *tpmax;
10030Sstevel@tonic-gate #if defined(lint) || defined(_lint)
10040Sstevel@tonic-gate uchar_t chr; /* lint likes this */
10050Sstevel@tonic-gate #else
10060Sstevel@tonic-gate int chr; /* not uchar_t; more efficient this way */
10070Sstevel@tonic-gate /* with WorkShop compiler */
10080Sstevel@tonic-gate #endif
10090Sstevel@tonic-gate int is_lcp, is_ctrl;
10100Sstevel@tonic-gate int code;
10110Sstevel@tonic-gate hrtime_t hrtime;
10120Sstevel@tonic-gate uint32_t flags; /* sampled copy of flags */
10130Sstevel@tonic-gate
10140Sstevel@tonic-gate state = (sppp_ahdlc_t *)q->q_ptr;
10150Sstevel@tonic-gate
10160Sstevel@tonic-gate /* Don't transmit anything obviously silly. */
10170Sstevel@tonic-gate msglen = msgsize(mp);
10180Sstevel@tonic-gate if (msglen < 4) {
10190Sstevel@tonic-gate KINCR(pks_outrunts);
10200Sstevel@tonic-gate freemsg(mp);
10210Sstevel@tonic-gate (void) putnextctl1(RD(q), M_CTL, PPPCTL_OERROR);
10220Sstevel@tonic-gate return (NULL);
10230Sstevel@tonic-gate }
10240Sstevel@tonic-gate
10250Sstevel@tonic-gate /*
10260Sstevel@tonic-gate * Allocate an output buffer just large enough for most cases.
10270Sstevel@tonic-gate * Based on original work in the ppp-2.2 AIX PPP driver, we
10280Sstevel@tonic-gate * estimate the output size as 1.25 * input message length
10290Sstevel@tonic-gate * plus 16. If this turns out to be too small, then we'll
10300Sstevel@tonic-gate * allocate exactly one additional buffer with two times the
10310Sstevel@tonic-gate * remaining input length (the maximum that could possibly be
10320Sstevel@tonic-gate * required).
10330Sstevel@tonic-gate */
10340Sstevel@tonic-gate outmp_len = msglen + (msglen >> 2) + 16;
10350Sstevel@tonic-gate outmp = allocb(outmp_len, BPRI_MED);
10360Sstevel@tonic-gate if (outmp == NULL)
10370Sstevel@tonic-gate goto outallocfail;
10380Sstevel@tonic-gate
10390Sstevel@tonic-gate tp = outmp->b_wptr;
10400Sstevel@tonic-gate
10410Sstevel@tonic-gate /*
10420Sstevel@tonic-gate * Check if our last transmit happened within FLAG_TIME, using
10430Sstevel@tonic-gate * the system's hrtime.
10440Sstevel@tonic-gate */
10450Sstevel@tonic-gate hrtime = gethrtime();
10460Sstevel@tonic-gate if (ABS(hrtime - state->sa_hrtime) > FLAG_TIME) {
10470Sstevel@tonic-gate *tp++ = PPP_FLAG;
10480Sstevel@tonic-gate }
10490Sstevel@tonic-gate state->sa_hrtime = hrtime;
10500Sstevel@tonic-gate bcopy((caddr_t)state->sa_xaccm, (caddr_t)loc_xaccm, sizeof (loc_xaccm));
10510Sstevel@tonic-gate flags = state->sa_flags;
10520Sstevel@tonic-gate
10530Sstevel@tonic-gate /*
10540Sstevel@tonic-gate * LCP messages must be sent using the default escaping
10550Sstevel@tonic-gate * (ACCM). We bend this rule a little to allow LCP
10560Sstevel@tonic-gate * Echo-Request through with the negotiated escaping so that
10570Sstevel@tonic-gate * we can detect bad negotiated ACCM values. If the ACCM is
10580Sstevel@tonic-gate * bad, echos will fail and take down the link.
10590Sstevel@tonic-gate */
10600Sstevel@tonic-gate is_lcp = is_ctrl = 0;
10610Sstevel@tonic-gate code = MSG_BYTE(mp, 0);
10620Sstevel@tonic-gate if (code == PPP_ALLSTATIONS) {
10630Sstevel@tonic-gate if (MSG_BYTE(mp, 1) == PPP_UI) {
10640Sstevel@tonic-gate code = MSG_BYTE(mp, 2);
10650Sstevel@tonic-gate if (code == (PPP_LCP >> 8) &&
10660Sstevel@tonic-gate MSG_BYTE(mp, 3) == (PPP_LCP & 0xFF)) {
10670Sstevel@tonic-gate if (LCP_USE_DFLT(mp))
10680Sstevel@tonic-gate is_lcp = 2;
10690Sstevel@tonic-gate else
10700Sstevel@tonic-gate is_lcp = 1; /* Echo-Request */
10710Sstevel@tonic-gate } else if (!(code & 1) && code > 0x3F)
10720Sstevel@tonic-gate is_ctrl = 1;
10730Sstevel@tonic-gate }
10740Sstevel@tonic-gate } else if (!(code & 1) && code > 0x3F)
10750Sstevel@tonic-gate is_ctrl = 1;
10760Sstevel@tonic-gate
10770Sstevel@tonic-gate /*
10780Sstevel@tonic-gate * If it's LCP and not just an LCP Echo-Request, then we need
10790Sstevel@tonic-gate * to drop back to default escaping rules temporarily.
10800Sstevel@tonic-gate */
10810Sstevel@tonic-gate if (is_lcp > 1) {
10820Sstevel@tonic-gate /*
10830Sstevel@tonic-gate * force escape on 0x00 through 0x1f
10840Sstevel@tonic-gate * and, for RFC 1662 (and ISO 3309:1991), 0x80-0x9f.
10850Sstevel@tonic-gate */
10860Sstevel@tonic-gate loc_xaccm[0] = 0xffffffff;
10870Sstevel@tonic-gate loc_xaccm[4] = 0xffffffff;
10880Sstevel@tonic-gate }
10890Sstevel@tonic-gate
10900Sstevel@tonic-gate fcs16 = PPPINITFCS16; /* Initial FCS is 0xffff */
10910Sstevel@tonic-gate fcs32 = PPPINITFCS32;
10920Sstevel@tonic-gate
10930Sstevel@tonic-gate /*
10940Sstevel@tonic-gate * Process this block and the rest (if any) attached to this
10950Sstevel@tonic-gate * one. Note that we quite intentionally ignore the type of
10960Sstevel@tonic-gate * the buffer. The caller has checked that the first buffer
10970Sstevel@tonic-gate * is M_DATA; all others must be so, and any that are not are
10980Sstevel@tonic-gate * harmless driver errors.
10990Sstevel@tonic-gate */
11000Sstevel@tonic-gate curout = outmp;
11010Sstevel@tonic-gate tpmax = outmp->b_datap->db_lim;
11020Sstevel@tonic-gate do {
11030Sstevel@tonic-gate dp = mp->b_rptr;
11040Sstevel@tonic-gate while (dp < (ep = mp->b_wptr)) {
11050Sstevel@tonic-gate /*
11060Sstevel@tonic-gate * Calculate maximum safe run length for inner loop,
11070Sstevel@tonic-gate * regardless of escaping.
11080Sstevel@tonic-gate */
11090Sstevel@tonic-gate outmp_len = (tpmax - tp) / 2;
11100Sstevel@tonic-gate if (dp + outmp_len < ep)
11110Sstevel@tonic-gate ep = dp + outmp_len;
11120Sstevel@tonic-gate
11130Sstevel@tonic-gate /*
11140Sstevel@tonic-gate * Select out on CRC type here to make the
11150Sstevel@tonic-gate * inner byte loop more efficient. (We could
11160Sstevel@tonic-gate * do both CRCs at all times if we wanted, but
11170Sstevel@tonic-gate * that ends up taking an extra 8 cycles per
11180Sstevel@tonic-gate * byte -- 47% overhead!)
11190Sstevel@tonic-gate */
11200Sstevel@tonic-gate if (flags & SAF_XMITCRC32) {
11210Sstevel@tonic-gate while (dp < ep) {
11220Sstevel@tonic-gate chr = *dp++;
11230Sstevel@tonic-gate fcs32 = PPPFCS32(fcs32, chr);
11240Sstevel@tonic-gate if (IN_TX_MAP(chr, loc_xaccm)) {
11250Sstevel@tonic-gate *tp++ = PPP_ESCAPE;
11260Sstevel@tonic-gate chr ^= PPP_TRANS;
11270Sstevel@tonic-gate }
11280Sstevel@tonic-gate *tp++ = chr;
11290Sstevel@tonic-gate }
11300Sstevel@tonic-gate } else {
11310Sstevel@tonic-gate while (dp < ep) {
11320Sstevel@tonic-gate chr = *dp++;
11330Sstevel@tonic-gate fcs16 = PPPFCS16(fcs16, chr);
11340Sstevel@tonic-gate if (IN_TX_MAP(chr, loc_xaccm)) {
11350Sstevel@tonic-gate *tp++ = PPP_ESCAPE;
11360Sstevel@tonic-gate chr ^= PPP_TRANS;
11370Sstevel@tonic-gate }
11380Sstevel@tonic-gate *tp++ = chr;
11390Sstevel@tonic-gate }
11400Sstevel@tonic-gate }
11410Sstevel@tonic-gate
11420Sstevel@tonic-gate /*
11430Sstevel@tonic-gate * If we limited our run length and we're now low
11440Sstevel@tonic-gate * on output space, then allocate a new output buffer.
11450Sstevel@tonic-gate * This should rarely happen, unless the output data
11460Sstevel@tonic-gate * has a lot of escapes.
11470Sstevel@tonic-gate */
11480Sstevel@tonic-gate if (ep != mp->b_wptr && tpmax - tp < 5) {
11490Sstevel@tonic-gate KINCR(pks_extrabufs);
11500Sstevel@tonic-gate /* Get remaining message length */
11510Sstevel@tonic-gate outmp_len = (mp->b_wptr - dp) +
11520Sstevel@tonic-gate msgsize(mp->b_cont);
11530Sstevel@tonic-gate /* Calculate maximum required space */
11540Sstevel@tonic-gate outmp_len = (outmp_len + PPP_FCS32LEN) * 2 + 1;
11550Sstevel@tonic-gate curout = allocb(outmp_len, BPRI_MED);
11560Sstevel@tonic-gate if ((outmp->b_cont = curout) == NULL)
11570Sstevel@tonic-gate goto outallocfail;
11580Sstevel@tonic-gate outmp->b_wptr = tp;
11590Sstevel@tonic-gate tp = curout->b_wptr;
11600Sstevel@tonic-gate tpmax = curout->b_datap->db_lim;
11610Sstevel@tonic-gate }
11620Sstevel@tonic-gate }
11630Sstevel@tonic-gate tmp = mp->b_cont;
11640Sstevel@tonic-gate freeb(mp);
11650Sstevel@tonic-gate mp = tmp;
11660Sstevel@tonic-gate } while (mp != NULL);
11670Sstevel@tonic-gate
11680Sstevel@tonic-gate /*
11690Sstevel@tonic-gate * Make sure we have enough remaining room to add the CRC (if
11700Sstevel@tonic-gate * any) and a trailing flag byte.
11710Sstevel@tonic-gate */
11720Sstevel@tonic-gate outmp_len = PPP_FCS32LEN * 2 + 1;
11730Sstevel@tonic-gate if (tpmax - tp < outmp_len) {
11740Sstevel@tonic-gate KINCR(pks_extrabufs);
11750Sstevel@tonic-gate curout = allocb(outmp_len, BPRI_MED);
11760Sstevel@tonic-gate if ((outmp->b_cont = curout) == NULL)
11770Sstevel@tonic-gate goto outallocfail;
11780Sstevel@tonic-gate outmp->b_wptr = tp;
11790Sstevel@tonic-gate tp = curout->b_wptr;
11800Sstevel@tonic-gate tpmax = curout->b_datap->db_lim;
11810Sstevel@tonic-gate }
11820Sstevel@tonic-gate
11830Sstevel@tonic-gate /*
11840Sstevel@tonic-gate * Network layer data is the only thing that can be sent with
11850Sstevel@tonic-gate * no CRC at all.
11860Sstevel@tonic-gate */
11870Sstevel@tonic-gate if ((flags & SAF_XMITCRCNONE) && !is_lcp && !is_ctrl)
11880Sstevel@tonic-gate goto nocrc;
11890Sstevel@tonic-gate
11900Sstevel@tonic-gate if (!(flags & SAF_XMITCRC32))
11910Sstevel@tonic-gate fcs32 = fcs16;
11920Sstevel@tonic-gate
11930Sstevel@tonic-gate /*
11940Sstevel@tonic-gate * Append the HDLC FCS, making sure that escaping is done on any
11950Sstevel@tonic-gate * necessary bytes. Note that the FCS bytes are in little-endian.
11960Sstevel@tonic-gate */
11970Sstevel@tonic-gate fcs32 = ~fcs32;
11980Sstevel@tonic-gate chr = fcs32 & 0xff;
11990Sstevel@tonic-gate if (IN_TX_MAP(chr, loc_xaccm)) {
12000Sstevel@tonic-gate *tp++ = PPP_ESCAPE;
12010Sstevel@tonic-gate chr ^= PPP_TRANS;
12020Sstevel@tonic-gate }
12030Sstevel@tonic-gate *tp++ = chr;
12040Sstevel@tonic-gate
12050Sstevel@tonic-gate chr = (fcs32 >> 8) & 0xff;
12060Sstevel@tonic-gate if (IN_TX_MAP(chr, loc_xaccm)) {
12070Sstevel@tonic-gate *tp++ = PPP_ESCAPE;
12080Sstevel@tonic-gate chr ^= PPP_TRANS;
12090Sstevel@tonic-gate }
12100Sstevel@tonic-gate *tp++ = chr;
12110Sstevel@tonic-gate
12120Sstevel@tonic-gate if (flags & SAF_XMITCRC32) {
12130Sstevel@tonic-gate chr = (fcs32 >> 16) & 0xff;
12140Sstevel@tonic-gate if (IN_TX_MAP(chr, loc_xaccm)) {
12150Sstevel@tonic-gate *tp++ = PPP_ESCAPE;
12160Sstevel@tonic-gate chr ^= PPP_TRANS;
12170Sstevel@tonic-gate }
12180Sstevel@tonic-gate *tp++ = chr;
12190Sstevel@tonic-gate
12200Sstevel@tonic-gate chr = (fcs32 >> 24) & 0xff;
12210Sstevel@tonic-gate if (IN_TX_MAP(chr, loc_xaccm)) {
12220Sstevel@tonic-gate *tp++ = PPP_ESCAPE;
12230Sstevel@tonic-gate chr ^= PPP_TRANS;
12240Sstevel@tonic-gate }
12250Sstevel@tonic-gate *tp++ = chr;
12260Sstevel@tonic-gate }
12270Sstevel@tonic-gate
12280Sstevel@tonic-gate nocrc:
12290Sstevel@tonic-gate /*
12300Sstevel@tonic-gate * And finally append the HDLC flag, and send it away
12310Sstevel@tonic-gate */
12320Sstevel@tonic-gate *tp++ = PPP_FLAG;
12330Sstevel@tonic-gate ASSERT(tp < tpmax);
12340Sstevel@tonic-gate curout->b_wptr = tp;
12350Sstevel@tonic-gate
12360Sstevel@tonic-gate state->sa_stats.ppp_obytes += msgsize(outmp);
12370Sstevel@tonic-gate state->sa_stats.ppp_opackets++;
12380Sstevel@tonic-gate
12390Sstevel@tonic-gate if (state->sa_flags & SAF_XMITDUMP)
12400Sstevel@tonic-gate ppp_dump_frame(state, outmp, "sent");
12410Sstevel@tonic-gate
12420Sstevel@tonic-gate KINCR(pks_dataout);
12430Sstevel@tonic-gate return (outmp);
12440Sstevel@tonic-gate
12450Sstevel@tonic-gate outallocfail:
12460Sstevel@tonic-gate KINCR(pks_outallocfails);
12470Sstevel@tonic-gate state->sa_stats.ppp_oerrors++;
12480Sstevel@tonic-gate freemsg(outmp);
12490Sstevel@tonic-gate freemsg(mp);
12500Sstevel@tonic-gate (void) putnextctl1(RD(q), M_CTL, PPPCTL_OERROR);
12510Sstevel@tonic-gate return (NULL);
12520Sstevel@tonic-gate }
12530Sstevel@tonic-gate
12540Sstevel@tonic-gate /*
12550Sstevel@tonic-gate * Handle end-of-frame excitement. This is here mostly because the Solaris
12560Sstevel@tonic-gate * C style rules require tab for indent and prohibit excessive indenting.
12570Sstevel@tonic-gate */
12580Sstevel@tonic-gate static mblk_t *
receive_frame(queue_t * q,mblk_t * outmp,ushort_t fcs16,uint32_t fcs32)12590Sstevel@tonic-gate receive_frame(queue_t *q, mblk_t *outmp, ushort_t fcs16, uint32_t fcs32)
12600Sstevel@tonic-gate {
12610Sstevel@tonic-gate sppp_ahdlc_t *state = (sppp_ahdlc_t *)q->q_ptr;
12620Sstevel@tonic-gate uchar_t *cp, *ep;
12630Sstevel@tonic-gate int is_lcp, is_ctrl, crclen;
12640Sstevel@tonic-gate ushort_t proto;
12650Sstevel@tonic-gate int i;
12660Sstevel@tonic-gate
12670Sstevel@tonic-gate cp = outmp->b_rptr;
12680Sstevel@tonic-gate if (cp[0] == PPP_ALLSTATIONS && cp[1] == PPP_UI)
12690Sstevel@tonic-gate cp += 2;
12700Sstevel@tonic-gate proto = *cp++;
12710Sstevel@tonic-gate if ((proto & 1) == 0)
12720Sstevel@tonic-gate proto = (proto << 8) + *cp++;
12730Sstevel@tonic-gate is_lcp = (proto == PPP_LCP);
12740Sstevel@tonic-gate is_ctrl = (proto >= 0x4000);
12750Sstevel@tonic-gate
12760Sstevel@tonic-gate /*
12770Sstevel@tonic-gate * To allow for renegotiation, LCP accepts good CRCs of either
12780Sstevel@tonic-gate * type at any time. Other control (non-network) packets must
12790Sstevel@tonic-gate * have either CRC-16 or CRC-32, as negotiated. Network layer
12800Sstevel@tonic-gate * packets may additionally omit the CRC entirely, if that was
12810Sstevel@tonic-gate * negotiated.
12820Sstevel@tonic-gate */
12830Sstevel@tonic-gate if ((is_lcp && (fcs16 == PPPGOODFCS16 || fcs32 == PPPGOODFCS32)) ||
12840Sstevel@tonic-gate ((fcs16 == PPPGOODFCS16 && !(state->sa_flags & SAF_RECVCRC32)) ||
1285*5640Scarlsonj (fcs32 == PPPGOODFCS32 &&
1286*5640Scarlsonj (state->sa_flags & SAF_RECVCRC32))) ||
12870Sstevel@tonic-gate (!is_ctrl && !is_lcp && (state->sa_flags & SAF_RECVCRCNONE))) {
12880Sstevel@tonic-gate
12890Sstevel@tonic-gate state->sa_stats.ppp_ipackets++;
12900Sstevel@tonic-gate if (is_lcp) {
12910Sstevel@tonic-gate crclen = (fcs16 == PPPGOODFCS16) ?
12920Sstevel@tonic-gate PPP_FCSLEN : PPP_FCS32LEN;
12930Sstevel@tonic-gate } else {
12940Sstevel@tonic-gate crclen = (state->sa_flags & SAF_RECVCRC32) ?
12950Sstevel@tonic-gate PPP_FCS32LEN : PPP_FCSLEN;
12960Sstevel@tonic-gate if (!is_ctrl && (state->sa_flags & SAF_RECVCRCNONE))
12970Sstevel@tonic-gate crclen = 0;
12980Sstevel@tonic-gate }
12990Sstevel@tonic-gate if (crclen != 0) {
13000Sstevel@tonic-gate i = adjmsg(outmp, -crclen);
13010Sstevel@tonic-gate ASSERT(i != 0);
13020Sstevel@tonic-gate #if defined(lint) || defined(_lint)
13030Sstevel@tonic-gate /* lint is happier this way in a non-DEBUG build */
13040Sstevel@tonic-gate i = i;
13050Sstevel@tonic-gate #endif
13060Sstevel@tonic-gate }
13070Sstevel@tonic-gate
13080Sstevel@tonic-gate if (proto == PPP_MUX) {
13090Sstevel@tonic-gate /* spppasyn_inpkt checks for PPP_MUX packets */
13100Sstevel@tonic-gate KINCR(pks_recvmux);
13110Sstevel@tonic-gate /* Remove headers */
13120Sstevel@tonic-gate outmp->b_rptr = cp;
13130Sstevel@tonic-gate return (spppasyn_inpkt(q, outmp));
13140Sstevel@tonic-gate }
13150Sstevel@tonic-gate
13160Sstevel@tonic-gate /*
13170Sstevel@tonic-gate * Sniff the received data stream. If we see an LCP
13180Sstevel@tonic-gate * Configure-Ack, then pick out the ACCM setting, if
13190Sstevel@tonic-gate * any, and configure now. This allows us to stay in
13200Sstevel@tonic-gate * sync in case the peer is already out of Establish
13210Sstevel@tonic-gate * phase.
13220Sstevel@tonic-gate */
13230Sstevel@tonic-gate if (is_lcp && *cp == 2) {
13240Sstevel@tonic-gate ep = outmp->b_wptr;
13250Sstevel@tonic-gate i = (cp[2] << 8) | cp[3];
13260Sstevel@tonic-gate if (i > ep - cp)
13270Sstevel@tonic-gate ep = cp; /* Discard junk */
13280Sstevel@tonic-gate else if (i < ep - cp)
13290Sstevel@tonic-gate ep = cp + i;
13300Sstevel@tonic-gate cp += 4;
13310Sstevel@tonic-gate while (cp + 2 < ep) {
13320Sstevel@tonic-gate if ((i = cp[1]) < 2)
13330Sstevel@tonic-gate i = 2;
13340Sstevel@tonic-gate if (cp + i > ep)
13350Sstevel@tonic-gate i = ep - cp;
13360Sstevel@tonic-gate if (cp[0] == 2 && i >= 6) {
13370Sstevel@tonic-gate state->sa_raccm = (cp[2] << 24) |
13380Sstevel@tonic-gate (cp[3] << 16) | (cp[4] << 8) |
13390Sstevel@tonic-gate cp[5];
13400Sstevel@tonic-gate break;
13410Sstevel@tonic-gate }
13420Sstevel@tonic-gate cp += i;
13430Sstevel@tonic-gate }
13440Sstevel@tonic-gate }
13450Sstevel@tonic-gate return (outmp);
13460Sstevel@tonic-gate } else {
13470Sstevel@tonic-gate KINCR(pks_incrcerrs);
13480Sstevel@tonic-gate cmn_err(CE_CONT, PPP_DRV_NAME "%d: bad fcs (len=%ld)\n",
13490Sstevel@tonic-gate state->sa_unit, msgsize(outmp));
13500Sstevel@tonic-gate
13510Sstevel@tonic-gate if (state->sa_flags & SAF_RECVDUMP)
13520Sstevel@tonic-gate ppp_dump_frame(state, outmp, "bad data");
13530Sstevel@tonic-gate
13540Sstevel@tonic-gate freemsg(outmp);
13550Sstevel@tonic-gate
13560Sstevel@tonic-gate state->sa_stats.ppp_ierrors++;
13570Sstevel@tonic-gate
13580Sstevel@tonic-gate (void) putnextctl1(q, M_CTL, PPPCTL_IERROR);
13590Sstevel@tonic-gate return (NULL);
13600Sstevel@tonic-gate }
13610Sstevel@tonic-gate }
13620Sstevel@tonic-gate
13630Sstevel@tonic-gate /*
13640Sstevel@tonic-gate * ahdlc_decode()
13650Sstevel@tonic-gate *
13660Sstevel@tonic-gate * Process received characters.
13670Sstevel@tonic-gate *
13680Sstevel@tonic-gate * This is handled as exclusive inner so that we don't get confused
13690Sstevel@tonic-gate * about the state. Returns a list of packets linked by b_next.
13700Sstevel@tonic-gate */
13710Sstevel@tonic-gate static mblk_t *
ahdlc_decode(queue_t * q,mblk_t * mp)13720Sstevel@tonic-gate ahdlc_decode(queue_t *q, mblk_t *mp)
13730Sstevel@tonic-gate {
13740Sstevel@tonic-gate sppp_ahdlc_t *state;
13750Sstevel@tonic-gate mblk_t *retmp; /* list of packets to return */
13760Sstevel@tonic-gate mblk_t *outmp; /* buffer for decoded data */
13770Sstevel@tonic-gate mblk_t *mpnext; /* temporary ptr for unlinking */
13780Sstevel@tonic-gate uchar_t *dp; /* pointer to input data */
13790Sstevel@tonic-gate uchar_t *dpend; /* end of input data */
13800Sstevel@tonic-gate uchar_t *tp; /* pointer to decoded output data */
13810Sstevel@tonic-gate uchar_t *tpmax; /* output buffer limit */
13820Sstevel@tonic-gate int flagtmp; /* temporary cache of flags */
13830Sstevel@tonic-gate #if defined(lint) || defined(_lint)
13840Sstevel@tonic-gate uchar_t chr; /* lint likes this */
13850Sstevel@tonic-gate #else
13860Sstevel@tonic-gate int chr; /* not uchar_t; more efficient this way */
13870Sstevel@tonic-gate /* with WorkShop compiler */
13880Sstevel@tonic-gate #endif
13890Sstevel@tonic-gate ushort_t fcs16; /* running CRC-16 */
13900Sstevel@tonic-gate uint32_t fcs32; /* running CRC-32 */
13910Sstevel@tonic-gate #ifdef HANDLE_ZERO_LENGTH
13920Sstevel@tonic-gate size_t nprocessed;
13930Sstevel@tonic-gate #endif
13940Sstevel@tonic-gate
13950Sstevel@tonic-gate state = (sppp_ahdlc_t *)q->q_ptr;
13960Sstevel@tonic-gate
13970Sstevel@tonic-gate KINCR(pks_datain);
13980Sstevel@tonic-gate
13990Sstevel@tonic-gate state->sa_stats.ppp_ibytes += msgsize(mp);
14000Sstevel@tonic-gate
14010Sstevel@tonic-gate if (state->sa_flags & SAF_RECVDUMP)
14020Sstevel@tonic-gate ppp_dump_frame(state, mp, "rcvd");
14030Sstevel@tonic-gate
14040Sstevel@tonic-gate flagtmp = state->sa_flags;
14050Sstevel@tonic-gate fcs16 = state->sa_infcs16;
14060Sstevel@tonic-gate fcs32 = state->sa_infcs32;
14070Sstevel@tonic-gate outmp = state->sa_rx_buf;
14080Sstevel@tonic-gate if (outmp == NULL) {
14090Sstevel@tonic-gate tp = tpmax = NULL;
14100Sstevel@tonic-gate } else {
14110Sstevel@tonic-gate tp = outmp->b_wptr;
14120Sstevel@tonic-gate tpmax = outmp->b_datap->db_lim;
14130Sstevel@tonic-gate }
14140Sstevel@tonic-gate #ifdef HANDLE_ZERO_LENGTH
14150Sstevel@tonic-gate nprocessed = 0;
14160Sstevel@tonic-gate #endif
14170Sstevel@tonic-gate
14180Sstevel@tonic-gate /*
14190Sstevel@tonic-gate * Main input processing loop. Loop over received buffers and
14200Sstevel@tonic-gate * each byte in each buffer. Note that we quite intentionally
14210Sstevel@tonic-gate * ignore the type of the buffer. The caller has checked that
14220Sstevel@tonic-gate * the first buffer is M_DATA; all others must be so, and any
14230Sstevel@tonic-gate * that are not are harmless driver errors.
14240Sstevel@tonic-gate */
14250Sstevel@tonic-gate retmp = NULL;
14260Sstevel@tonic-gate while (mp != NULL) {
14270Sstevel@tonic-gate
14280Sstevel@tonic-gate /* Innermost loop -- examine bytes in buffer. */
14290Sstevel@tonic-gate dpend = mp->b_wptr;
14300Sstevel@tonic-gate dp = mp->b_rptr;
14310Sstevel@tonic-gate #ifdef HANDLE_ZERO_LENGTH
14320Sstevel@tonic-gate nprocessed += dpend - dp;
14330Sstevel@tonic-gate #endif
14340Sstevel@tonic-gate for (; dp < dpend; dp++) {
14350Sstevel@tonic-gate chr = *dp;
14360Sstevel@tonic-gate
14370Sstevel@tonic-gate /*
14380Sstevel@tonic-gate * This should detect the lack of an 8-bit
14390Sstevel@tonic-gate * communication channel, which is necessary
14400Sstevel@tonic-gate * for PPP to work.
14410Sstevel@tonic-gate */
14420Sstevel@tonic-gate flagtmp |= charflags[chr];
14430Sstevel@tonic-gate
14440Sstevel@tonic-gate /*
14450Sstevel@tonic-gate * So we have a HDLC flag ...
14460Sstevel@tonic-gate */
14470Sstevel@tonic-gate if (chr == PPP_FLAG) {
14480Sstevel@tonic-gate
14490Sstevel@tonic-gate /*
14500Sstevel@tonic-gate * If there's no received buffer, then
14510Sstevel@tonic-gate * just ignore this frame marker.
14520Sstevel@tonic-gate */
14530Sstevel@tonic-gate if ((flagtmp & SAF_IFLUSH) || outmp == NULL) {
14540Sstevel@tonic-gate flagtmp &= ~SAF_IFLUSH & ~SAF_ESCAPED;
14550Sstevel@tonic-gate continue;
14560Sstevel@tonic-gate }
14570Sstevel@tonic-gate
14580Sstevel@tonic-gate /*
14590Sstevel@tonic-gate * Per RFC 1662 -- silently discard
14600Sstevel@tonic-gate * runt frames (fewer than 4 octets
14610Sstevel@tonic-gate * with 16 bit CRC) and frames that
14620Sstevel@tonic-gate * end in 7D 7E (abort sequence).
14630Sstevel@tonic-gate * These are not counted as errors.
14640Sstevel@tonic-gate *
14650Sstevel@tonic-gate * (We could just reset the pointers
14660Sstevel@tonic-gate * and reuse the buffer, but this is a
14670Sstevel@tonic-gate * rarely used error path and not
14680Sstevel@tonic-gate * worth the optimization.)
14690Sstevel@tonic-gate */
14700Sstevel@tonic-gate if ((flagtmp & SAF_ESCAPED) ||
14710Sstevel@tonic-gate tp - outmp->b_rptr < 2 + PPP_FCSLEN) {
14720Sstevel@tonic-gate if (flagtmp & SAF_ESCAPED)
14730Sstevel@tonic-gate KINCR(pks_inaborts);
14740Sstevel@tonic-gate else
14750Sstevel@tonic-gate KINCR(pks_inrunts);
14760Sstevel@tonic-gate if (state->sa_flags & SAF_RECVDUMP) {
14770Sstevel@tonic-gate outmp->b_wptr = tp;
14780Sstevel@tonic-gate ppp_dump_frame(state, outmp,
14790Sstevel@tonic-gate "runt");
14800Sstevel@tonic-gate }
14810Sstevel@tonic-gate freemsg(outmp);
14820Sstevel@tonic-gate flagtmp &= ~SAF_ESCAPED;
14830Sstevel@tonic-gate } else {
14840Sstevel@tonic-gate /* Handle the received frame */
14850Sstevel@tonic-gate outmp->b_wptr = tp;
14860Sstevel@tonic-gate outmp = receive_frame(q, outmp, fcs16,
14870Sstevel@tonic-gate fcs32);
14880Sstevel@tonic-gate retmp = sppp_mappend(retmp, outmp);
14890Sstevel@tonic-gate }
14900Sstevel@tonic-gate
14910Sstevel@tonic-gate outmp = NULL;
14920Sstevel@tonic-gate tp = tpmax = NULL;
14930Sstevel@tonic-gate
14940Sstevel@tonic-gate continue;
14950Sstevel@tonic-gate }
14960Sstevel@tonic-gate
14970Sstevel@tonic-gate /* If we're waiting for a new frame, then drop data. */
14980Sstevel@tonic-gate if (flagtmp & SAF_IFLUSH) {
14990Sstevel@tonic-gate continue;
15000Sstevel@tonic-gate }
15010Sstevel@tonic-gate
15020Sstevel@tonic-gate /*
15030Sstevel@tonic-gate * Start of new frame. Allocate a receive
15040Sstevel@tonic-gate * buffer large enough to store a frame (after
15050Sstevel@tonic-gate * un-escaping) of at least 1500 octets plus
15060Sstevel@tonic-gate * the CRC. If MRU is negotiated to be more
15070Sstevel@tonic-gate * than the default, then allocate that much.
15080Sstevel@tonic-gate * In addition, we add an extra 32-bytes for a
15090Sstevel@tonic-gate * fudge factor, in case the peer doesn't do
15100Sstevel@tonic-gate * arithmetic very well.
15110Sstevel@tonic-gate */
15120Sstevel@tonic-gate if (outmp == NULL) {
15130Sstevel@tonic-gate int maxlen;
15140Sstevel@tonic-gate
15150Sstevel@tonic-gate if ((maxlen = state->sa_mru) < PPP_MRU)
1516*5640Scarlsonj maxlen = PPP_MRU;
15170Sstevel@tonic-gate maxlen += PPP_FCS32LEN + 32;
15180Sstevel@tonic-gate outmp = allocb(maxlen, BPRI_MED);
15190Sstevel@tonic-gate
15200Sstevel@tonic-gate /*
15210Sstevel@tonic-gate * If allocation fails, try again on
15220Sstevel@tonic-gate * the next frame. (Go into discard
15230Sstevel@tonic-gate * mode.)
15240Sstevel@tonic-gate */
15250Sstevel@tonic-gate if (outmp == NULL) {
15260Sstevel@tonic-gate KINCR(pks_inallocfails);
15270Sstevel@tonic-gate flagtmp |= SAF_IFLUSH;
15280Sstevel@tonic-gate continue;
15290Sstevel@tonic-gate }
15300Sstevel@tonic-gate
15310Sstevel@tonic-gate tp = outmp->b_wptr;
15320Sstevel@tonic-gate tpmax = outmp->b_datap->db_lim;
15330Sstevel@tonic-gate
15340Sstevel@tonic-gate /* Neither flag can possibly be set here. */
15350Sstevel@tonic-gate flagtmp &= ~(SAF_IFLUSH | SAF_ESCAPED);
15360Sstevel@tonic-gate fcs16 = PPPINITFCS16;
15370Sstevel@tonic-gate fcs32 = PPPINITFCS32;
15380Sstevel@tonic-gate }
15390Sstevel@tonic-gate
15400Sstevel@tonic-gate /*
15410Sstevel@tonic-gate * If the peer sends us a character that's in
15420Sstevel@tonic-gate * our receive character map, then that's
15430Sstevel@tonic-gate * junk. Discard it without changing state.
15440Sstevel@tonic-gate * If he previously sent us an escape
15450Sstevel@tonic-gate * character, then toggle this one and
15460Sstevel@tonic-gate * continue. Otherwise, if he's now sending
15470Sstevel@tonic-gate * escape, set the flag for next time.
15480Sstevel@tonic-gate */
15490Sstevel@tonic-gate if (IN_RX_MAP(chr, state->sa_raccm)) {
15500Sstevel@tonic-gate KINCR(pks_inbadchars);
15510Sstevel@tonic-gate KOR(pks_inbadcharmask, 1 << chr);
15520Sstevel@tonic-gate continue;
15530Sstevel@tonic-gate }
15540Sstevel@tonic-gate if (flagtmp & SAF_ESCAPED) {
15550Sstevel@tonic-gate chr ^= PPP_TRANS;
15560Sstevel@tonic-gate flagtmp &= ~SAF_ESCAPED;
15570Sstevel@tonic-gate } else if (chr == PPP_ESCAPE) {
15580Sstevel@tonic-gate flagtmp |= SAF_ESCAPED;
15590Sstevel@tonic-gate continue;
15600Sstevel@tonic-gate }
15610Sstevel@tonic-gate
15620Sstevel@tonic-gate /*
15630Sstevel@tonic-gate * Unless the peer is confused about the
15640Sstevel@tonic-gate * negotiated MRU, we should never get a frame
15650Sstevel@tonic-gate * that is too long. If it happens, toss it
15660Sstevel@tonic-gate * away and begin discarding data until we see
15670Sstevel@tonic-gate * the end of the frame.
15680Sstevel@tonic-gate */
15690Sstevel@tonic-gate if (tp < tpmax) {
15700Sstevel@tonic-gate fcs16 = PPPFCS16(fcs16, chr);
15710Sstevel@tonic-gate fcs32 = PPPFCS32(fcs32, chr);
15720Sstevel@tonic-gate *tp++ = chr;
15730Sstevel@tonic-gate } else {
15740Sstevel@tonic-gate KINCR(pks_intoolongs);
15750Sstevel@tonic-gate cmn_err(CE_CONT, PPP_DRV_NAME
15760Sstevel@tonic-gate "%d: frame too long (%d bytes)\n",
15770Sstevel@tonic-gate state->sa_unit,
15780Sstevel@tonic-gate (int)(tpmax - outmp->b_rptr));
15790Sstevel@tonic-gate
15800Sstevel@tonic-gate freemsg(outmp);
15810Sstevel@tonic-gate outmp = NULL;
15820Sstevel@tonic-gate tp = tpmax = NULL;
15830Sstevel@tonic-gate flagtmp |= SAF_IFLUSH;
15840Sstevel@tonic-gate }
15850Sstevel@tonic-gate }
15860Sstevel@tonic-gate
15870Sstevel@tonic-gate /*
15880Sstevel@tonic-gate * Free the buffer we just processed and move on to
15890Sstevel@tonic-gate * the next one.
15900Sstevel@tonic-gate */
15910Sstevel@tonic-gate mpnext = mp->b_cont;
15920Sstevel@tonic-gate freeb(mp);
15930Sstevel@tonic-gate mp = mpnext;
15940Sstevel@tonic-gate }
15950Sstevel@tonic-gate state->sa_flags = flagtmp;
15960Sstevel@tonic-gate if ((state->sa_rx_buf = outmp) != NULL)
15970Sstevel@tonic-gate outmp->b_wptr = tp;
15980Sstevel@tonic-gate state->sa_infcs16 = fcs16;
15990Sstevel@tonic-gate state->sa_infcs32 = fcs32;
16000Sstevel@tonic-gate
16010Sstevel@tonic-gate #ifdef HANDLE_ZERO_LENGTH
16020Sstevel@tonic-gate if (nprocessed <= 0) {
16030Sstevel@tonic-gate outmp = allocb(0, BPRI_MED);
16040Sstevel@tonic-gate if (outmp != NULL) {
16050Sstevel@tonic-gate outmp->b_datap->db_type = M_HANGUP;
16060Sstevel@tonic-gate retmp = sppp_mappend(retmp, outmp);
16070Sstevel@tonic-gate }
16080Sstevel@tonic-gate }
16090Sstevel@tonic-gate #endif
16100Sstevel@tonic-gate return (retmp);
16110Sstevel@tonic-gate }
16120Sstevel@tonic-gate
16130Sstevel@tonic-gate /*
16140Sstevel@tonic-gate * Nifty packet dumper; copied from AIX 4.1 port. This routine dumps
16150Sstevel@tonic-gate * the raw received and transmitted data through syslog. This allows
16160Sstevel@tonic-gate * debug of communications problems without resorting to a line
16170Sstevel@tonic-gate * analyzer.
16180Sstevel@tonic-gate *
16190Sstevel@tonic-gate * The expression "3*BYTES_PER_LINE" used frequently here represents
16200Sstevel@tonic-gate * the size of each hex value printed -- two hex digits and a space.
16210Sstevel@tonic-gate */
16220Sstevel@tonic-gate #define BYTES_PER_LINE 8
16230Sstevel@tonic-gate static void
ppp_dump_frame(sppp_ahdlc_t * state,mblk_t * mptr,const char * msg)16240Sstevel@tonic-gate ppp_dump_frame(sppp_ahdlc_t *state, mblk_t *mptr, const char *msg)
16250Sstevel@tonic-gate {
16260Sstevel@tonic-gate /*
16270Sstevel@tonic-gate * Buffer is big enough for hex digits, two spaces, ASCII output,
16280Sstevel@tonic-gate * and one NUL byte.
16290Sstevel@tonic-gate */
16300Sstevel@tonic-gate char buf[3 * BYTES_PER_LINE + 2 + BYTES_PER_LINE + 1];
16310Sstevel@tonic-gate uchar_t *rptr, *eptr;
16320Sstevel@tonic-gate int i, chr;
16330Sstevel@tonic-gate char *bp;
16340Sstevel@tonic-gate static const char digits[] = "0123456789abcdef";
16350Sstevel@tonic-gate
16360Sstevel@tonic-gate cmn_err(CE_CONT, "!ppp_async%d: %s %ld bytes\n", state->sa_unit,
16370Sstevel@tonic-gate msg, msgsize(mptr));
16380Sstevel@tonic-gate i = 0;
16390Sstevel@tonic-gate bp = buf;
16400Sstevel@tonic-gate /* Add filler spaces between hex output and ASCII */
16410Sstevel@tonic-gate buf[3 * BYTES_PER_LINE] = ' ';
16420Sstevel@tonic-gate buf[3 * BYTES_PER_LINE + 1] = ' ';
16430Sstevel@tonic-gate /* Add NUL byte at end */
16440Sstevel@tonic-gate buf[sizeof (buf) - 1] = '\0';
16450Sstevel@tonic-gate while (mptr != NULL) {
16460Sstevel@tonic-gate rptr = mptr->b_rptr; /* get pointer to beginning */
16470Sstevel@tonic-gate eptr = mptr->b_wptr;
16480Sstevel@tonic-gate while (rptr < eptr) {
16490Sstevel@tonic-gate chr = *rptr++;
16500Sstevel@tonic-gate /* convert byte to ascii hex */
16510Sstevel@tonic-gate *bp++ = digits[chr >> 4];
16520Sstevel@tonic-gate *bp++ = digits[chr & 0xf];
16530Sstevel@tonic-gate *bp++ = ' ';
16540Sstevel@tonic-gate /* Insert ASCII past hex output and filler */
16550Sstevel@tonic-gate buf[3 * BYTES_PER_LINE + 2 + i] =
16560Sstevel@tonic-gate (chr >= 0x20 && chr <= 0x7E) ? (char)chr : '.';
16570Sstevel@tonic-gate i++;
16580Sstevel@tonic-gate if (i >= BYTES_PER_LINE) {
16590Sstevel@tonic-gate cmn_err(CE_CONT, "!ppp%d: %s\n", state->sa_unit,
16600Sstevel@tonic-gate buf);
16610Sstevel@tonic-gate bp = buf;
16620Sstevel@tonic-gate i = 0;
16630Sstevel@tonic-gate }
16640Sstevel@tonic-gate }
16650Sstevel@tonic-gate mptr = mptr->b_cont;
16660Sstevel@tonic-gate }
16670Sstevel@tonic-gate if (bp > buf) {
16680Sstevel@tonic-gate /* fill over unused hex display positions */
16690Sstevel@tonic-gate while (bp < buf + 3 * BYTES_PER_LINE)
16700Sstevel@tonic-gate *bp++ = ' ';
16710Sstevel@tonic-gate /* terminate ASCII string at right position */
16720Sstevel@tonic-gate buf[3 * BYTES_PER_LINE + 2 + i] = '\0';
16730Sstevel@tonic-gate cmn_err(CE_CONT, "!ppp%d: %s\n", state->sa_unit, buf);
16740Sstevel@tonic-gate }
16750Sstevel@tonic-gate }
16760Sstevel@tonic-gate
16770Sstevel@tonic-gate static mblk_t *
spppasyn_muxencode(queue_t * q,mblk_t * mp)16780Sstevel@tonic-gate spppasyn_muxencode(queue_t *q, mblk_t *mp)
16790Sstevel@tonic-gate {
16800Sstevel@tonic-gate sppp_ahdlc_t *state = (sppp_ahdlc_t *)q->q_ptr;
16810Sstevel@tonic-gate uint32_t len;
16820Sstevel@tonic-gate uint32_t nlen;
16830Sstevel@tonic-gate ushort_t protolen;
16840Sstevel@tonic-gate uint32_t hdrlen;
16850Sstevel@tonic-gate ushort_t proto;
16860Sstevel@tonic-gate mblk_t *new_frame;
16870Sstevel@tonic-gate mblk_t *tmp;
16880Sstevel@tonic-gate mblk_t *send_frame;
16890Sstevel@tonic-gate ushort_t i;
16900Sstevel@tonic-gate
16910Sstevel@tonic-gate len = msgdsize(mp);
16920Sstevel@tonic-gate i = 0;
16930Sstevel@tonic-gate protolen = 1;
16940Sstevel@tonic-gate proto = MSG_BYTE(mp, i);
16950Sstevel@tonic-gate
16960Sstevel@tonic-gate if (proto == PPP_ALLSTATIONS) {
16970Sstevel@tonic-gate len -= 2;
16980Sstevel@tonic-gate i += 2;
16990Sstevel@tonic-gate proto = MSG_BYTE(mp, i);
17000Sstevel@tonic-gate }
17010Sstevel@tonic-gate
17020Sstevel@tonic-gate ++i;
17030Sstevel@tonic-gate if ((proto & 1) == 0) {
17040Sstevel@tonic-gate proto = (proto << 8) + MSG_BYTE(mp, i);
17050Sstevel@tonic-gate protolen++;
17060Sstevel@tonic-gate }
17070Sstevel@tonic-gate
17080Sstevel@tonic-gate hdrlen = i - 1;
17090Sstevel@tonic-gate
17100Sstevel@tonic-gate send_frame = NULL;
17110Sstevel@tonic-gate if (len > PPP_MAX_MUX_LEN || (proto & 0x8000)) {
17120Sstevel@tonic-gate
17130Sstevel@tonic-gate /* send the queued frames */
17140Sstevel@tonic-gate if (state->sa_mqhead != NULL) {
17150Sstevel@tonic-gate /* increment counter if it is MUX pkt */
17160Sstevel@tonic-gate if (state->sa_mqtail != NULL)
17170Sstevel@tonic-gate KINCR(pks_sentmux);
17180Sstevel@tonic-gate send_frame = ahdlc_encode(q, state->sa_mqhead);
17190Sstevel@tonic-gate }
17200Sstevel@tonic-gate
17210Sstevel@tonic-gate /* send the current frame */
17220Sstevel@tonic-gate mp = ahdlc_encode(q, mp);
17230Sstevel@tonic-gate send_frame = sppp_mcat(send_frame, mp);
17240Sstevel@tonic-gate
17250Sstevel@tonic-gate /* reset the state values over here */
17260Sstevel@tonic-gate RESET_MUX_VALUES(state);
17270Sstevel@tonic-gate return (send_frame);
17280Sstevel@tonic-gate }
17290Sstevel@tonic-gate
17300Sstevel@tonic-gate /* len + 1 , since we add the mux overhead */
17310Sstevel@tonic-gate nlen = len + 1;
17320Sstevel@tonic-gate /* subtract the protocol length if protocol matches */
17330Sstevel@tonic-gate if (state->sa_proto == proto)
17340Sstevel@tonic-gate nlen -= protolen;
17350Sstevel@tonic-gate
17360Sstevel@tonic-gate send_frame = NULL;
17370Sstevel@tonic-gate if ((state->sa_mqlen + nlen) >= state->sa_mru) {
17380Sstevel@tonic-gate
17390Sstevel@tonic-gate /* send the existing queued frames */
17400Sstevel@tonic-gate if (state->sa_mqhead != NULL) {
17410Sstevel@tonic-gate /* increment counter if it is MUX pkt */
17420Sstevel@tonic-gate if (state->sa_mqtail != NULL)
17430Sstevel@tonic-gate KINCR(pks_sentmux);
17440Sstevel@tonic-gate send_frame = ahdlc_encode(q, state->sa_mqhead);
17450Sstevel@tonic-gate }
17460Sstevel@tonic-gate
17470Sstevel@tonic-gate /* reset state values */
17480Sstevel@tonic-gate RESET_MUX_VALUES(state);
17490Sstevel@tonic-gate }
17500Sstevel@tonic-gate
17510Sstevel@tonic-gate /* add the current frame to the queue */
17520Sstevel@tonic-gate if (state->sa_mqhead != NULL) {
17530Sstevel@tonic-gate
17540Sstevel@tonic-gate if (state->sa_mqtail == NULL) {
17550Sstevel@tonic-gate
17560Sstevel@tonic-gate /*
17570Sstevel@tonic-gate * this is the first mblk in the queue create
17580Sstevel@tonic-gate * a new frame to hold the PPP MUX header
17590Sstevel@tonic-gate */
17600Sstevel@tonic-gate if ((new_frame = allocb(PPP_HDRLEN+1,
17610Sstevel@tonic-gate BPRI_MED)) == NULL) {
17620Sstevel@tonic-gate return (send_frame);
17630Sstevel@tonic-gate }
17640Sstevel@tonic-gate
17650Sstevel@tonic-gate if (!IS_COMP_AC(state)) {
17660Sstevel@tonic-gate /* add the header */
17670Sstevel@tonic-gate *new_frame->b_wptr++ = PPP_ALLSTATIONS;
17680Sstevel@tonic-gate *new_frame->b_wptr++ = PPP_UI;
17690Sstevel@tonic-gate }
17700Sstevel@tonic-gate
17710Sstevel@tonic-gate /* do protocol compression */
17720Sstevel@tonic-gate if (IS_COMP_PROT(state)) {
17730Sstevel@tonic-gate *new_frame->b_wptr++ = PPP_MUX;
17740Sstevel@tonic-gate } else {
17750Sstevel@tonic-gate *new_frame->b_wptr++ = 0;
17760Sstevel@tonic-gate *new_frame->b_wptr++ = PPP_MUX;
17770Sstevel@tonic-gate }
17780Sstevel@tonic-gate
17790Sstevel@tonic-gate *new_frame->b_wptr++ = PFF |
17800Sstevel@tonic-gate (state->sa_mqlen - protolen - 1);
17810Sstevel@tonic-gate
17820Sstevel@tonic-gate if (DB_REF(mp) > 1) {
17830Sstevel@tonic-gate tmp = copymsg(state->sa_mqhead);
17840Sstevel@tonic-gate freemsg(state->sa_mqhead);
17850Sstevel@tonic-gate if ((state->sa_mqhead = tmp) == NULL) {
17860Sstevel@tonic-gate return (send_frame);
17870Sstevel@tonic-gate }
17880Sstevel@tonic-gate }
17890Sstevel@tonic-gate
17900Sstevel@tonic-gate if (state->sa_mqhead->b_rptr[0] == PPP_ALLSTATIONS)
17910Sstevel@tonic-gate state->sa_mqhead->b_rptr += 2;
17920Sstevel@tonic-gate
17930Sstevel@tonic-gate linkb(new_frame, state->sa_mqhead);
17940Sstevel@tonic-gate state->sa_mqtail = state->sa_mqhead;
17950Sstevel@tonic-gate /* point mqtail to the last mblk_t */
17960Sstevel@tonic-gate while (state->sa_mqtail->b_cont != NULL)
17970Sstevel@tonic-gate state->sa_mqtail = state->sa_mqtail->b_cont;
17980Sstevel@tonic-gate
17990Sstevel@tonic-gate /* change state->sa_mqhead */
18000Sstevel@tonic-gate state->sa_mqhead = new_frame;
18010Sstevel@tonic-gate
18020Sstevel@tonic-gate }
18030Sstevel@tonic-gate
18040Sstevel@tonic-gate if (state->sa_proto == proto) {
18050Sstevel@tonic-gate
18060Sstevel@tonic-gate /* Check if the mblk_t is being referenced */
18070Sstevel@tonic-gate if (DB_REF(mp) > 1) {
18080Sstevel@tonic-gate tmp = copymsg(mp);
18090Sstevel@tonic-gate freemsg(mp);
18100Sstevel@tonic-gate if ((mp = tmp) == NULL) {
18110Sstevel@tonic-gate return (send_frame);
18120Sstevel@tonic-gate }
18130Sstevel@tonic-gate }
18140Sstevel@tonic-gate
18150Sstevel@tonic-gate /*
18160Sstevel@tonic-gate * match,can remove the protocol field
18170Sstevel@tonic-gate * and write data there
18180Sstevel@tonic-gate */
18190Sstevel@tonic-gate mp->b_rptr += hdrlen;
18200Sstevel@tonic-gate /*
18210Sstevel@tonic-gate * protolen - 1 ,because the the byte with
18220Sstevel@tonic-gate * the PFF bit and the length field have
18230Sstevel@tonic-gate * to added
18240Sstevel@tonic-gate */
18250Sstevel@tonic-gate mp->b_rptr += (protolen - 1);
18260Sstevel@tonic-gate *mp->b_rptr = (len - protolen) & 0xff;
18270Sstevel@tonic-gate
18280Sstevel@tonic-gate } else {
18290Sstevel@tonic-gate /*
18300Sstevel@tonic-gate * no match, there are three options
18310Sstevel@tonic-gate * 1. write in mp
18320Sstevel@tonic-gate * 2. write in mqtail
18330Sstevel@tonic-gate * 3. alloc a new blk for just one byte
18340Sstevel@tonic-gate */
18350Sstevel@tonic-gate /* Check if the mblk_t is being referenced */
18360Sstevel@tonic-gate if (DB_REF(mp) > 1) {
18370Sstevel@tonic-gate tmp = copymsg(mp);
18380Sstevel@tonic-gate freemsg(mp);
18390Sstevel@tonic-gate if ((mp = tmp) == NULL) {
18400Sstevel@tonic-gate return (send_frame);
18410Sstevel@tonic-gate }
18420Sstevel@tonic-gate }
18430Sstevel@tonic-gate
18440Sstevel@tonic-gate if (hdrlen != 0) {
18450Sstevel@tonic-gate
18460Sstevel@tonic-gate mp->b_rptr += (hdrlen-1);
18470Sstevel@tonic-gate *mp->b_rptr = PFF | (len);
18480Sstevel@tonic-gate
18490Sstevel@tonic-gate } else if (state->sa_mqtail->b_wptr <
1850*5640Scarlsonj DB_LIM(state->sa_mqtail)) {
18510Sstevel@tonic-gate *state->sa_mqtail->b_wptr++ = PFF |len;
18520Sstevel@tonic-gate } else {
18530Sstevel@tonic-gate /* allocate a new mblk & add the byte */
18540Sstevel@tonic-gate /* write the data */
18550Sstevel@tonic-gate if ((new_frame = allocb(1, BPRI_MED))
18560Sstevel@tonic-gate == NULL) {
18570Sstevel@tonic-gate freemsg(mp);
18580Sstevel@tonic-gate return (send_frame);
18590Sstevel@tonic-gate }
18600Sstevel@tonic-gate *new_frame->b_wptr++ = PFF | (len);
18610Sstevel@tonic-gate linkb(state->sa_mqtail, new_frame);
18620Sstevel@tonic-gate }
18630Sstevel@tonic-gate
18640Sstevel@tonic-gate /* update proto */
18650Sstevel@tonic-gate state->sa_proto = proto;
18660Sstevel@tonic-gate }
18670Sstevel@tonic-gate
18680Sstevel@tonic-gate linkb(state->sa_mqtail, mp);
18690Sstevel@tonic-gate state->sa_mqtail = mp;
18700Sstevel@tonic-gate while (state->sa_mqtail->b_cont != NULL)
18710Sstevel@tonic-gate state->sa_mqtail = state->sa_mqtail->b_cont;
18720Sstevel@tonic-gate state->sa_mqlen += nlen;
18730Sstevel@tonic-gate
18740Sstevel@tonic-gate } else {
18750Sstevel@tonic-gate state->sa_mqhead = mp;
18760Sstevel@tonic-gate state->sa_mqlen = len + protolen + 1;
18770Sstevel@tonic-gate state->sa_proto = proto;
18780Sstevel@tonic-gate }
18790Sstevel@tonic-gate
18800Sstevel@tonic-gate if (state->sa_timeout_id == 0) {
18810Sstevel@tonic-gate state->sa_timeout_id = qtimeout(q, spppasyn_timer, q,
18820Sstevel@tonic-gate (drv_usectohz(state->sa_timeout_usec)));
18830Sstevel@tonic-gate }
18840Sstevel@tonic-gate return (send_frame);
18850Sstevel@tonic-gate }
18860Sstevel@tonic-gate
18870Sstevel@tonic-gate /*
18880Sstevel@tonic-gate * Called from receive frame, this routine checks if it is a PPP_MUX
18890Sstevel@tonic-gate * packet and demuxes it. The returned pointer is a chain of mblks
18900Sstevel@tonic-gate * using b_next and representing the demultiplexed packets.
18910Sstevel@tonic-gate */
18920Sstevel@tonic-gate static mblk_t *
spppasyn_inpkt(queue_t * q,mblk_t * mp)18930Sstevel@tonic-gate spppasyn_inpkt(queue_t *q, mblk_t *mp)
18940Sstevel@tonic-gate {
18950Sstevel@tonic-gate sppp_ahdlc_t *state = (sppp_ahdlc_t *)q->q_ptr;
18960Sstevel@tonic-gate ushort_t proto;
18970Sstevel@tonic-gate ushort_t prev_proto;
18980Sstevel@tonic-gate uint32_t len; /* length of subframe */
18990Sstevel@tonic-gate uchar_t muxhdr;
19000Sstevel@tonic-gate mblk_t *hdrmp;
19010Sstevel@tonic-gate mblk_t *subframe;
19020Sstevel@tonic-gate mblk_t *retmp;
19030Sstevel@tonic-gate
19040Sstevel@tonic-gate if (!(mp->b_rptr[0] & PFF)) {
19050Sstevel@tonic-gate KINCR(pks_inmuxerrs);
19060Sstevel@tonic-gate (void) putnextctl1(q, M_CTL, PPPCTL_IERROR);
19070Sstevel@tonic-gate freemsg(mp);
19080Sstevel@tonic-gate return (NULL);
19090Sstevel@tonic-gate }
19100Sstevel@tonic-gate
19110Sstevel@tonic-gate /* initialise the Last protocol and protocol length */
19120Sstevel@tonic-gate prev_proto = 0;
19130Sstevel@tonic-gate
19140Sstevel@tonic-gate /*
19150Sstevel@tonic-gate * Taking into granted that the decoded frame is contiguous
19160Sstevel@tonic-gate */
19170Sstevel@tonic-gate retmp = NULL;
19180Sstevel@tonic-gate while (mp->b_rptr < mp->b_wptr) {
19190Sstevel@tonic-gate
19200Sstevel@tonic-gate /*
19210Sstevel@tonic-gate * get the last protocol, protocol length
19220Sstevel@tonic-gate * and the length of the message
19230Sstevel@tonic-gate */
19240Sstevel@tonic-gate
19250Sstevel@tonic-gate /* protocol field flag and length */
19260Sstevel@tonic-gate muxhdr = mp->b_rptr[0];
19270Sstevel@tonic-gate len = muxhdr & ~PFF;
19280Sstevel@tonic-gate
19290Sstevel@tonic-gate mp->b_rptr++;
19300Sstevel@tonic-gate
19310Sstevel@tonic-gate /* check if there and enough bytes left in pkt */
19320Sstevel@tonic-gate if (MBLKL(mp) < len) {
19330Sstevel@tonic-gate KINCR(pks_inmuxerrs);
19340Sstevel@tonic-gate (void) putnextctl1(q, M_CTL, PPPCTL_IERROR);
19350Sstevel@tonic-gate break;
19360Sstevel@tonic-gate }
19370Sstevel@tonic-gate
19380Sstevel@tonic-gate /* allocate memory for the header length */
19390Sstevel@tonic-gate if ((hdrmp = allocb(PPP_HDRLEN, BPRI_MED)) == NULL) {
19400Sstevel@tonic-gate KINCR(pks_inallocfails);
19410Sstevel@tonic-gate break;
19420Sstevel@tonic-gate }
19430Sstevel@tonic-gate
19440Sstevel@tonic-gate /* add the ppp header to the pkt */
19450Sstevel@tonic-gate *hdrmp->b_wptr++ = PPP_ALLSTATIONS;
19460Sstevel@tonic-gate *hdrmp->b_wptr++ = PPP_UI;
19470Sstevel@tonic-gate
19480Sstevel@tonic-gate /* check if the protocol field flag is set */
19490Sstevel@tonic-gate if (muxhdr & PFF) {
19500Sstevel@tonic-gate
19510Sstevel@tonic-gate /* get the protocol */
19520Sstevel@tonic-gate proto = MSG_BYTE(mp, 0);
19530Sstevel@tonic-gate if ((proto & 1) == 0)
19540Sstevel@tonic-gate proto = (proto << 8) + MSG_BYTE(mp, 1);
19550Sstevel@tonic-gate
19560Sstevel@tonic-gate /* reset values */
19570Sstevel@tonic-gate prev_proto = proto;
19580Sstevel@tonic-gate } else {
19590Sstevel@tonic-gate if (!IS_DECOMP_PROT(state))
19600Sstevel@tonic-gate *hdrmp->b_wptr++ = prev_proto >> 8;
19610Sstevel@tonic-gate *hdrmp->b_wptr++ = (prev_proto & 0xff);
19620Sstevel@tonic-gate }
19630Sstevel@tonic-gate
19640Sstevel@tonic-gate /* get the payload from the MUXed packet */
19650Sstevel@tonic-gate subframe = dupmsg(mp);
19660Sstevel@tonic-gate subframe->b_wptr = mp->b_rptr + len;
19670Sstevel@tonic-gate
19680Sstevel@tonic-gate /* link the subframe to the new frame */
19690Sstevel@tonic-gate linkb(hdrmp, subframe);
19700Sstevel@tonic-gate
19710Sstevel@tonic-gate /* do a putnext */
19720Sstevel@tonic-gate retmp = sppp_mappend(retmp, hdrmp);
19730Sstevel@tonic-gate
19740Sstevel@tonic-gate /* move the read pointer beyond this subframe */
19750Sstevel@tonic-gate mp->b_rptr += len;
19760Sstevel@tonic-gate }
19770Sstevel@tonic-gate
19780Sstevel@tonic-gate freemsg(mp);
19790Sstevel@tonic-gate return (retmp);
19800Sstevel@tonic-gate }
19810Sstevel@tonic-gate
19820Sstevel@tonic-gate
19830Sstevel@tonic-gate /*
19840Sstevel@tonic-gate * timer routine which sends out the queued pkts *
19850Sstevel@tonic-gate */
19860Sstevel@tonic-gate static void
spppasyn_timer(void * arg)19870Sstevel@tonic-gate spppasyn_timer(void *arg)
19880Sstevel@tonic-gate {
19890Sstevel@tonic-gate queue_t *q;
19900Sstevel@tonic-gate sppp_ahdlc_t *state;
19910Sstevel@tonic-gate mblk_t *mp;
19920Sstevel@tonic-gate
19930Sstevel@tonic-gate ASSERT(arg);
19940Sstevel@tonic-gate q = (queue_t *)arg;
19950Sstevel@tonic-gate state = (sppp_ahdlc_t *)q->q_ptr;
19960Sstevel@tonic-gate
19970Sstevel@tonic-gate if (state->sa_mqhead != NULL) {
19980Sstevel@tonic-gate /* increment counter */
19990Sstevel@tonic-gate if (state->sa_mqtail != NULL)
20000Sstevel@tonic-gate KINCR(pks_sentmux);
20010Sstevel@tonic-gate if ((mp = ahdlc_encode(q, state->sa_mqhead)) != NULL)
20020Sstevel@tonic-gate putnext(q, mp);
20030Sstevel@tonic-gate /* reset the state values over here */
20040Sstevel@tonic-gate RESET_MUX_VALUES(state);
20050Sstevel@tonic-gate }
20060Sstevel@tonic-gate /* clear timeout_id */
20070Sstevel@tonic-gate state->sa_timeout_id = 0;
20080Sstevel@tonic-gate }
2009