17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * spppasyn.c - STREAMS module for doing PPP asynchronous HDLC.
37c478bd9Sstevel@tonic-gate *
4*002c70ffScarlsonj * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
57c478bd9Sstevel@tonic-gate * Use is subject to license terms.
67c478bd9Sstevel@tonic-gate *
77c478bd9Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software and its
87c478bd9Sstevel@tonic-gate * documentation is hereby granted, provided that the above copyright
97c478bd9Sstevel@tonic-gate * notice appears in all copies.
107c478bd9Sstevel@tonic-gate *
117c478bd9Sstevel@tonic-gate * SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF
127c478bd9Sstevel@tonic-gate * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
137c478bd9Sstevel@tonic-gate * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
147c478bd9Sstevel@tonic-gate * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
157c478bd9Sstevel@tonic-gate * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
167c478bd9Sstevel@tonic-gate * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES
177c478bd9Sstevel@tonic-gate *
187c478bd9Sstevel@tonic-gate * Copyright (c) 1994 The Australian National University.
197c478bd9Sstevel@tonic-gate * All rights reserved.
207c478bd9Sstevel@tonic-gate *
217c478bd9Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software and its
227c478bd9Sstevel@tonic-gate * documentation is hereby granted, provided that the above copyright
237c478bd9Sstevel@tonic-gate * notice appears in all copies. This software is provided without any
247c478bd9Sstevel@tonic-gate * warranty, express or implied. The Australian National University
257c478bd9Sstevel@tonic-gate * makes no representations about the suitability of this software for
267c478bd9Sstevel@tonic-gate * any purpose.
277c478bd9Sstevel@tonic-gate *
287c478bd9Sstevel@tonic-gate * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
297c478bd9Sstevel@tonic-gate * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
307c478bd9Sstevel@tonic-gate * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
317c478bd9Sstevel@tonic-gate * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY
327c478bd9Sstevel@tonic-gate * OF SUCH DAMAGE.
337c478bd9Sstevel@tonic-gate *
347c478bd9Sstevel@tonic-gate * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
357c478bd9Sstevel@tonic-gate * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
367c478bd9Sstevel@tonic-gate * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
377c478bd9Sstevel@tonic-gate * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
387c478bd9Sstevel@tonic-gate * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
397c478bd9Sstevel@tonic-gate * OR MODIFICATIONS.
407c478bd9Sstevel@tonic-gate *
417c478bd9Sstevel@tonic-gate * $Id: ppp_ahdlc.c,v 1.16 2000/03/06 19:38:12 masputra Exp $
427c478bd9Sstevel@tonic-gate */
437c478bd9Sstevel@tonic-gate
447c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
457c478bd9Sstevel@tonic-gate
467c478bd9Sstevel@tonic-gate #include <sys/types.h>
477c478bd9Sstevel@tonic-gate #include <sys/param.h>
487c478bd9Sstevel@tonic-gate #include <sys/stream.h>
497c478bd9Sstevel@tonic-gate #include <sys/strsun.h>
507c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
517c478bd9Sstevel@tonic-gate #include <sys/errno.h>
527c478bd9Sstevel@tonic-gate #include <sys/conf.h>
537c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
547c478bd9Sstevel@tonic-gate #include <sys/crc32.h>
557c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
567c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate #include <net/ppp_defs.h>
597c478bd9Sstevel@tonic-gate #include <net/pppio.h>
607c478bd9Sstevel@tonic-gate
617c478bd9Sstevel@tonic-gate #include "s_common.h"
627c478bd9Sstevel@tonic-gate
637c478bd9Sstevel@tonic-gate #ifdef DEBUG
647c478bd9Sstevel@tonic-gate #define REPORT_CRC_TYPE
657c478bd9Sstevel@tonic-gate #endif
667c478bd9Sstevel@tonic-gate #include "spppasyn.h"
677c478bd9Sstevel@tonic-gate
687c478bd9Sstevel@tonic-gate /*
697c478bd9Sstevel@tonic-gate * This is used to tag official Solaris sources. Please do not define
707c478bd9Sstevel@tonic-gate * "INTERNAL_BUILD" when building this software outside of Sun
717c478bd9Sstevel@tonic-gate * Microsystems.
727c478bd9Sstevel@tonic-gate */
737c478bd9Sstevel@tonic-gate #ifdef INTERNAL_BUILD
747c478bd9Sstevel@tonic-gate /* MODINFO is limited to 32 characters. */
75*002c70ffScarlsonj const char spppasyn_module_description[] = "PPP 4.0 AHDLC";
767c478bd9Sstevel@tonic-gate #else /* INTERNAL_BUILD */
777c478bd9Sstevel@tonic-gate const char spppasyn_module_description[] = "ANU PPP AHDLC $Revision: 1.16$";
787c478bd9Sstevel@tonic-gate
797c478bd9Sstevel@tonic-gate /* LINTED */
807c478bd9Sstevel@tonic-gate static const char buildtime[] = "Built " __DATE__ " at " __TIME__
817c478bd9Sstevel@tonic-gate #ifdef DEBUG
827c478bd9Sstevel@tonic-gate " DEBUG"
837c478bd9Sstevel@tonic-gate #endif
847c478bd9Sstevel@tonic-gate "\n";
857c478bd9Sstevel@tonic-gate #endif /* INTERNAL_BUILD */
867c478bd9Sstevel@tonic-gate
877c478bd9Sstevel@tonic-gate static int spppasyn_open(queue_t *, dev_t *, int, int, cred_t *);
887c478bd9Sstevel@tonic-gate static int spppasyn_close(queue_t *, int, cred_t *);
897c478bd9Sstevel@tonic-gate static int spppasyn_wput(queue_t *, mblk_t *);
907c478bd9Sstevel@tonic-gate static int spppasyn_rput(queue_t *, mblk_t *);
917c478bd9Sstevel@tonic-gate static mblk_t *ahdlc_encode(queue_t *, mblk_t *);
927c478bd9Sstevel@tonic-gate static mblk_t *ahdlc_decode(queue_t *, mblk_t *);
937c478bd9Sstevel@tonic-gate static void spppasyn_timer(void *);
947c478bd9Sstevel@tonic-gate static mblk_t *spppasyn_inpkt(queue_t *, mblk_t *);
957c478bd9Sstevel@tonic-gate static mblk_t *spppasyn_muxencode(queue_t *, mblk_t *);
967c478bd9Sstevel@tonic-gate
977c478bd9Sstevel@tonic-gate #define RESET_MUX_VALUES(x) { \
987c478bd9Sstevel@tonic-gate x->sa_mqhead = x->sa_mqtail = NULL; \
997c478bd9Sstevel@tonic-gate x->sa_proto = 0; \
1007c478bd9Sstevel@tonic-gate x->sa_mqlen = 0; \
1017c478bd9Sstevel@tonic-gate }
1027c478bd9Sstevel@tonic-gate #define IS_XMUX_ENABLED(x) \
1037c478bd9Sstevel@tonic-gate ((x)->sa_flags & X_MUXMASK)
1047c478bd9Sstevel@tonic-gate #define IS_RMUX_ENABLED(x) \
1057c478bd9Sstevel@tonic-gate ((x)->sa_flags & R_MUXMASK)
1067c478bd9Sstevel@tonic-gate #define IS_COMP_AC(x) \
1077c478bd9Sstevel@tonic-gate ((x)->sa_flags & SAF_XCOMP_AC)
1087c478bd9Sstevel@tonic-gate #define IS_COMP_PROT(x) \
1097c478bd9Sstevel@tonic-gate ((x)->sa_flags & SAF_XCOMP_PROT)
1107c478bd9Sstevel@tonic-gate #define IS_DECOMP_PROT(x) \
1117c478bd9Sstevel@tonic-gate ((x)->sa_flags & SAF_RDECOMP_PROT)
1127c478bd9Sstevel@tonic-gate
1137c478bd9Sstevel@tonic-gate /*
1147c478bd9Sstevel@tonic-gate * Don't send HDLC start flag if last transmit is within 1.5 seconds -
1157c478bd9Sstevel@tonic-gate * FLAG_TIME is defined in nanoseconds.
1167c478bd9Sstevel@tonic-gate */
1177c478bd9Sstevel@tonic-gate #define FLAG_TIME 1500000000ul
1187c478bd9Sstevel@tonic-gate
1197c478bd9Sstevel@tonic-gate /*
1207c478bd9Sstevel@tonic-gate * The usual AHDLC implementation enables the default escaping for all
1217c478bd9Sstevel@tonic-gate * LCP frames. LCP_USE_DFLT() is used in this implementation to
1227c478bd9Sstevel@tonic-gate * modify this rule slightly. If the code number happens to be
1237c478bd9Sstevel@tonic-gate * Echo-Request, Echo-Reply, or Discard-Request (each of which may be
1247c478bd9Sstevel@tonic-gate * sent only when LCP is in Opened state), then one may also use the
1257c478bd9Sstevel@tonic-gate * negotiated ACCM; the RFC is silent on this. The theory is that
1267c478bd9Sstevel@tonic-gate * pppd can construct Echo-Request messages that are guaranteed to
1277c478bd9Sstevel@tonic-gate * fail if the negotiated ACCM is bad.
1287c478bd9Sstevel@tonic-gate */
1297c478bd9Sstevel@tonic-gate #define LCP_USE_DFLT(mp) ((code = MSG_BYTE((mp), 4)) < 9 || code > 11)
1307c478bd9Sstevel@tonic-gate
1317c478bd9Sstevel@tonic-gate /*
1327c478bd9Sstevel@tonic-gate * Extract bit c from map m, to determine if character c needs to be
1337c478bd9Sstevel@tonic-gate * escaped. Map 'm' is a pointer to a 256 bit map; 8 words of 32 bits
1347c478bd9Sstevel@tonic-gate * each.
1357c478bd9Sstevel@tonic-gate */
1367c478bd9Sstevel@tonic-gate #define IN_TX_MAP(c, m) \
1377c478bd9Sstevel@tonic-gate ((m)[(c) >> 5] & (1 << ((c) & 0x1f)))
1387c478bd9Sstevel@tonic-gate
1397c478bd9Sstevel@tonic-gate /*
1407c478bd9Sstevel@tonic-gate * Checks the 32-bit receive ACCM to see if the byte should have been
1417c478bd9Sstevel@tonic-gate * escaped by peer.
1427c478bd9Sstevel@tonic-gate */
1437c478bd9Sstevel@tonic-gate #define IN_RX_MAP(c, m) (((c) < 0x20) && ((m) & (1 << (c))))
1447c478bd9Sstevel@tonic-gate
1457c478bd9Sstevel@tonic-gate static struct module_info spppasyn_modinfo = {
1467c478bd9Sstevel@tonic-gate AHDLC_MOD_ID, /* mi_idnum */
1477c478bd9Sstevel@tonic-gate AHDLC_MOD_NAME, /* mi_idname */
1487c478bd9Sstevel@tonic-gate 0, /* mi_minpsz */
1497c478bd9Sstevel@tonic-gate INFPSZ, /* mi_maxpsz */
1507c478bd9Sstevel@tonic-gate 0, /* mi_hiwat */
1517c478bd9Sstevel@tonic-gate 0 /* mi_lowat */
1527c478bd9Sstevel@tonic-gate };
1537c478bd9Sstevel@tonic-gate
1547c478bd9Sstevel@tonic-gate static struct qinit spppasyn_rinit = {
1557c478bd9Sstevel@tonic-gate spppasyn_rput, /* qi_putp */
1567c478bd9Sstevel@tonic-gate NULL, /* qi_srvp */
1577c478bd9Sstevel@tonic-gate spppasyn_open, /* qi_qopen */
1587c478bd9Sstevel@tonic-gate spppasyn_close, /* qi_qclose */
1597c478bd9Sstevel@tonic-gate NULL, /* qi_qadmin */
1607c478bd9Sstevel@tonic-gate &spppasyn_modinfo, /* qi_minfo */
1617c478bd9Sstevel@tonic-gate NULL /* qi_mstat */
1627c478bd9Sstevel@tonic-gate };
1637c478bd9Sstevel@tonic-gate
1647c478bd9Sstevel@tonic-gate static struct qinit spppasyn_winit = {
1657c478bd9Sstevel@tonic-gate spppasyn_wput, /* qi_putp */
1667c478bd9Sstevel@tonic-gate NULL, /* qi_srvp */
1677c478bd9Sstevel@tonic-gate NULL, /* qi_qopen */
1687c478bd9Sstevel@tonic-gate NULL, /* qi_qclose */
1697c478bd9Sstevel@tonic-gate NULL, /* qi_qadmin */
1707c478bd9Sstevel@tonic-gate &spppasyn_modinfo, /* qi_minfo */
1717c478bd9Sstevel@tonic-gate NULL /* qi_mstat */
1727c478bd9Sstevel@tonic-gate };
1737c478bd9Sstevel@tonic-gate
1747c478bd9Sstevel@tonic-gate struct streamtab spppasyn_tab = {
1757c478bd9Sstevel@tonic-gate &spppasyn_rinit, /* st_rdinit */
1767c478bd9Sstevel@tonic-gate &spppasyn_winit, /* st_wrinit */
1777c478bd9Sstevel@tonic-gate NULL, /* st_muxrinit */
1787c478bd9Sstevel@tonic-gate NULL, /* st_muxwinit */
1797c478bd9Sstevel@tonic-gate };
1807c478bd9Sstevel@tonic-gate
1817c478bd9Sstevel@tonic-gate /* Matches above structure. */
1827c478bd9Sstevel@tonic-gate static const char *kstat_names[] = {
1837c478bd9Sstevel@tonic-gate "ioctls", "ioctlsfwd", "ioctlserr", "ctls",
1847c478bd9Sstevel@tonic-gate "ctlsfwd", "ctlserr", "inbadchars", "inbadcharmask",
1857c478bd9Sstevel@tonic-gate "inaborts", "inrunts", "inallocfails", "intoolongs",
1867c478bd9Sstevel@tonic-gate "outrunts", "outallocfails", "incrcerrs", "unknownwrs",
1877c478bd9Sstevel@tonic-gate "unknownrds", "hangups", "datain", "dataout",
1887c478bd9Sstevel@tonic-gate "extrabufs", "sentmux", "recvmux", "inmuxerrs",
1897c478bd9Sstevel@tonic-gate #ifdef REPORT_CRC_TYPE
1907c478bd9Sstevel@tonic-gate "incrctype", "outcrctype",
1917c478bd9Sstevel@tonic-gate #endif
1927c478bd9Sstevel@tonic-gate };
1937c478bd9Sstevel@tonic-gate
1947c478bd9Sstevel@tonic-gate /* So. This is why we have optimizing compilers. */
1957c478bd9Sstevel@tonic-gate #define KVAL(vn) state->sa_kstats.vn.value.ui32
1967c478bd9Sstevel@tonic-gate #define KSET(vn, v) KVAL(vn) = (v)
1977c478bd9Sstevel@tonic-gate #define KADD(vn, v) KSET(vn, KVAL(vn) + (v))
1987c478bd9Sstevel@tonic-gate #define KOR(vn, v) KSET(vn, KVAL(vn) | (v))
1997c478bd9Sstevel@tonic-gate #define KINCR(vn) KADD(vn, 1)
2007c478bd9Sstevel@tonic-gate
2017c478bd9Sstevel@tonic-gate static void ppp_dump_frame(sppp_ahdlc_t *state, mblk_t *mptr,
2027c478bd9Sstevel@tonic-gate const char *msg);
2037c478bd9Sstevel@tonic-gate
2047c478bd9Sstevel@tonic-gate /*
2057c478bd9Sstevel@tonic-gate * RCV_B7_1, etc., defined in net/pppio.h, are stored in flags also.
2067c478bd9Sstevel@tonic-gate */
2077c478bd9Sstevel@tonic-gate #define RCV_FLAGS (RCV_B7_1 | RCV_B7_0 | RCV_ODDP | RCV_EVNP)
2087c478bd9Sstevel@tonic-gate
2097c478bd9Sstevel@tonic-gate /*
2107c478bd9Sstevel@tonic-gate * FCS lookup table as calculated by genfcstab.
2117c478bd9Sstevel@tonic-gate */
2127c478bd9Sstevel@tonic-gate static ushort_t fcstab[256] = {
2137c478bd9Sstevel@tonic-gate 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
2147c478bd9Sstevel@tonic-gate 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
2157c478bd9Sstevel@tonic-gate 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
2167c478bd9Sstevel@tonic-gate 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
2177c478bd9Sstevel@tonic-gate 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
2187c478bd9Sstevel@tonic-gate 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
2197c478bd9Sstevel@tonic-gate 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
2207c478bd9Sstevel@tonic-gate 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
2217c478bd9Sstevel@tonic-gate 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
2227c478bd9Sstevel@tonic-gate 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
2237c478bd9Sstevel@tonic-gate 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
2247c478bd9Sstevel@tonic-gate 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
2257c478bd9Sstevel@tonic-gate 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
2267c478bd9Sstevel@tonic-gate 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
2277c478bd9Sstevel@tonic-gate 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
2287c478bd9Sstevel@tonic-gate 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
2297c478bd9Sstevel@tonic-gate 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
2307c478bd9Sstevel@tonic-gate 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
2317c478bd9Sstevel@tonic-gate 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
2327c478bd9Sstevel@tonic-gate 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
2337c478bd9Sstevel@tonic-gate 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
2347c478bd9Sstevel@tonic-gate 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
2357c478bd9Sstevel@tonic-gate 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
2367c478bd9Sstevel@tonic-gate 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
2377c478bd9Sstevel@tonic-gate 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
2387c478bd9Sstevel@tonic-gate 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
2397c478bd9Sstevel@tonic-gate 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
2407c478bd9Sstevel@tonic-gate 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
2417c478bd9Sstevel@tonic-gate 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
2427c478bd9Sstevel@tonic-gate 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
2437c478bd9Sstevel@tonic-gate 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
2447c478bd9Sstevel@tonic-gate 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
2457c478bd9Sstevel@tonic-gate };
2467c478bd9Sstevel@tonic-gate
2477c478bd9Sstevel@tonic-gate /*
2487c478bd9Sstevel@tonic-gate * Per-character flags for accumulating input errors. Flags are
2497c478bd9Sstevel@tonic-gate * accumulated for bit 7 set to 0, bit 7 set to 1, even parity
2507c478bd9Sstevel@tonic-gate * characters, and odd parity characters. The link should see all
2517c478bd9Sstevel@tonic-gate * four in the very first LCP Configure-Request if all is ok. (C0 is
2527c478bd9Sstevel@tonic-gate * even parity and has bit 7 set to 1, and 23 is odd parity and has
2537c478bd9Sstevel@tonic-gate * bit 7 set to 0.)
2547c478bd9Sstevel@tonic-gate */
2557c478bd9Sstevel@tonic-gate static uchar_t charflags[256] = {
2567c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP,
2577c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2587c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP,
2597c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP,
2607c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP,
2617c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2627c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2637c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2647c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP,
2657c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2667c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP,
2677c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP,
2687c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP,
2697c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP,
2707c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP,
2717c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP,
2727c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP,
2737c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2747c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP,
2757c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP,
2767c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP,
2777c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2787c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2797c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2807c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP,
2817c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2827c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2837c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2847c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_EVNP,
2857c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2867c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2877c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2887c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP,
2897c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2907c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP,
2917c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP,
2927c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP,
2937c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2947c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2957c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2967c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_ODDP,
2977c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_0|RCV_EVNP,
2987c478bd9Sstevel@tonic-gate RCV_B7_0|RCV_EVNP, RCV_B7_0|RCV_ODDP, RCV_B7_1|RCV_ODDP,
2997c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3007c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_ODDP,
3017c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3027c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3037c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3047c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_ODDP,
3057c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_EVNP,
3067c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_ODDP,
3077c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3087c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_ODDP,
3097c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3107c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3117c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3127c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_EVNP,
3137c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3147c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3157c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3167c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_ODDP,
3177c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3187c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3197c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3207c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_ODDP,
3217c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_EVNP,
3227c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_ODDP,
3237c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3247c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_ODDP,
3257c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_EVNP,
3267c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_EVNP,
3277c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_EVNP,
3287c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_ODDP,
3297c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_EVNP,
3307c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_ODDP,
3317c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3327c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_ODDP,
3337c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3347c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3357c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3367c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_ODDP,
3377c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_EVNP,
3387c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_ODDP,
3397c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP,
3407c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP, RCV_B7_1|RCV_ODDP, RCV_B7_1|RCV_ODDP,
3417c478bd9Sstevel@tonic-gate RCV_B7_1|RCV_EVNP
3427c478bd9Sstevel@tonic-gate };
3437c478bd9Sstevel@tonic-gate
3447c478bd9Sstevel@tonic-gate /*
3457c478bd9Sstevel@tonic-gate * Append two lists; preserve message boundaries.
3467c478bd9Sstevel@tonic-gate * Warning: uses b_next.
3477c478bd9Sstevel@tonic-gate */
3487c478bd9Sstevel@tonic-gate static mblk_t *
sppp_mappend(mblk_t * m1,mblk_t * m2)3497c478bd9Sstevel@tonic-gate sppp_mappend(mblk_t *m1, mblk_t *m2)
3507c478bd9Sstevel@tonic-gate {
3517c478bd9Sstevel@tonic-gate mblk_t *mret;
3527c478bd9Sstevel@tonic-gate
3537c478bd9Sstevel@tonic-gate if (m1 == NULL)
3547c478bd9Sstevel@tonic-gate return (m2);
3557c478bd9Sstevel@tonic-gate if (m2 == NULL)
3567c478bd9Sstevel@tonic-gate return (m1);
3577c478bd9Sstevel@tonic-gate
3587c478bd9Sstevel@tonic-gate mret = m1;
3597c478bd9Sstevel@tonic-gate while (m1->b_next != NULL)
3607c478bd9Sstevel@tonic-gate m1 = m1->b_next;
3617c478bd9Sstevel@tonic-gate m1->b_next = m2;
3627c478bd9Sstevel@tonic-gate return (mret);
3637c478bd9Sstevel@tonic-gate }
3647c478bd9Sstevel@tonic-gate
3657c478bd9Sstevel@tonic-gate /*
3667c478bd9Sstevel@tonic-gate * Concatenate two mblk lists.
3677c478bd9Sstevel@tonic-gate */
3687c478bd9Sstevel@tonic-gate static mblk_t *
sppp_mcat(mblk_t * m1,mblk_t * m2)3697c478bd9Sstevel@tonic-gate sppp_mcat(mblk_t *m1, mblk_t *m2)
3707c478bd9Sstevel@tonic-gate {
3717c478bd9Sstevel@tonic-gate mblk_t *mret;
3727c478bd9Sstevel@tonic-gate
3737c478bd9Sstevel@tonic-gate if (m1 == NULL)
3747c478bd9Sstevel@tonic-gate return (m2);
3757c478bd9Sstevel@tonic-gate if (m2 == NULL)
3767c478bd9Sstevel@tonic-gate return (m1);
3777c478bd9Sstevel@tonic-gate
3787c478bd9Sstevel@tonic-gate mret = m1;
3797c478bd9Sstevel@tonic-gate while (m1->b_cont != NULL)
3807c478bd9Sstevel@tonic-gate m1 = m1->b_cont;
3817c478bd9Sstevel@tonic-gate m1->b_cont = m2;
3827c478bd9Sstevel@tonic-gate return (mret);
3837c478bd9Sstevel@tonic-gate }
3847c478bd9Sstevel@tonic-gate
3857c478bd9Sstevel@tonic-gate /*
3867c478bd9Sstevel@tonic-gate * spppasyn_open()
3877c478bd9Sstevel@tonic-gate *
3887c478bd9Sstevel@tonic-gate * STREAMS module open (entry) point. Called when spppasyn is pushed
3897c478bd9Sstevel@tonic-gate * onto an asynchronous serial stream.
3907c478bd9Sstevel@tonic-gate */
3917c478bd9Sstevel@tonic-gate /* ARGSUSED */
3927c478bd9Sstevel@tonic-gate static int
spppasyn_open(queue_t * q,dev_t * devp,int flag,int sflag,cred_t * credp)3937c478bd9Sstevel@tonic-gate spppasyn_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp)
3947c478bd9Sstevel@tonic-gate {
3957c478bd9Sstevel@tonic-gate sppp_ahdlc_t *state;
3967c478bd9Sstevel@tonic-gate
3977c478bd9Sstevel@tonic-gate ASSERT(q != NULL);
3987c478bd9Sstevel@tonic-gate
3997c478bd9Sstevel@tonic-gate if (q->q_ptr != NULL) {
4007c478bd9Sstevel@tonic-gate return (0); /* return if already opened */
4017c478bd9Sstevel@tonic-gate }
4027c478bd9Sstevel@tonic-gate
4037c478bd9Sstevel@tonic-gate if (sflag != MODOPEN) {
4047c478bd9Sstevel@tonic-gate return (EINVAL); /* only open as a module */
4057c478bd9Sstevel@tonic-gate }
4067c478bd9Sstevel@tonic-gate
4077c478bd9Sstevel@tonic-gate state = (sppp_ahdlc_t *)kmem_zalloc(sizeof (sppp_ahdlc_t), KM_SLEEP);
4087c478bd9Sstevel@tonic-gate ASSERT(state != NULL);
4097c478bd9Sstevel@tonic-gate
4107c478bd9Sstevel@tonic-gate q->q_ptr = (caddr_t)state;
4117c478bd9Sstevel@tonic-gate WR(q)->q_ptr = (caddr_t)state;
4127c478bd9Sstevel@tonic-gate
4137c478bd9Sstevel@tonic-gate state->sa_xaccm[0] = 0xffffffff; /* escape 0x00 through 0x1f */
4147c478bd9Sstevel@tonic-gate state->sa_xaccm[3] = 0x60000000; /* escape 0x7d and 0x7e */
4157c478bd9Sstevel@tonic-gate state->sa_mru = PPP_MRU; /* default of 1500 bytes */
4167c478bd9Sstevel@tonic-gate
4177c478bd9Sstevel@tonic-gate qprocson(q);
4187c478bd9Sstevel@tonic-gate
4197c478bd9Sstevel@tonic-gate return (0);
4207c478bd9Sstevel@tonic-gate }
4217c478bd9Sstevel@tonic-gate
4227c478bd9Sstevel@tonic-gate /*
4237c478bd9Sstevel@tonic-gate * spppasyn_close()
4247c478bd9Sstevel@tonic-gate *
4257c478bd9Sstevel@tonic-gate * STREAMS module close (exit) point
4267c478bd9Sstevel@tonic-gate */
4277c478bd9Sstevel@tonic-gate /* ARGSUSED */
4287c478bd9Sstevel@tonic-gate static int
spppasyn_close(queue_t * q,int flag,cred_t * credp)4297c478bd9Sstevel@tonic-gate spppasyn_close(queue_t *q, int flag, cred_t *credp)
4307c478bd9Sstevel@tonic-gate {
4317c478bd9Sstevel@tonic-gate sppp_ahdlc_t *state;
4327c478bd9Sstevel@tonic-gate
4337c478bd9Sstevel@tonic-gate ASSERT(q != NULL);
4347c478bd9Sstevel@tonic-gate state = (sppp_ahdlc_t *)q->q_ptr;
4357c478bd9Sstevel@tonic-gate ASSERT(state != NULL);
4367c478bd9Sstevel@tonic-gate
4377c478bd9Sstevel@tonic-gate /* We're leaving now. No more calls, please. */
4387c478bd9Sstevel@tonic-gate qprocsoff(q);
4397c478bd9Sstevel@tonic-gate
4407c478bd9Sstevel@tonic-gate if (state->sa_rx_buf != NULL) {
4417c478bd9Sstevel@tonic-gate freemsg(state->sa_rx_buf);
4427c478bd9Sstevel@tonic-gate state->sa_rx_buf = NULL;
4437c478bd9Sstevel@tonic-gate }
4447c478bd9Sstevel@tonic-gate
4457c478bd9Sstevel@tonic-gate if (state->sa_ksp != NULL) {
4467c478bd9Sstevel@tonic-gate kstat_delete(state->sa_ksp);
4477c478bd9Sstevel@tonic-gate state->sa_ksp = NULL;
4487c478bd9Sstevel@tonic-gate }
4497c478bd9Sstevel@tonic-gate
4507c478bd9Sstevel@tonic-gate if (state->sa_mqhead != NULL)
4517c478bd9Sstevel@tonic-gate freemsg(state->sa_mqhead);
4527c478bd9Sstevel@tonic-gate /* remove the time out routine */
4537c478bd9Sstevel@tonic-gate if (state->sa_timeout_id != 0)
4547c478bd9Sstevel@tonic-gate (void) quntimeout(q, state->sa_timeout_id);
4557c478bd9Sstevel@tonic-gate
4567c478bd9Sstevel@tonic-gate q->q_ptr = NULL;
4577c478bd9Sstevel@tonic-gate WR(q)->q_ptr = NULL;
4587c478bd9Sstevel@tonic-gate kmem_free(state, sizeof (sppp_ahdlc_t));
4597c478bd9Sstevel@tonic-gate
4607c478bd9Sstevel@tonic-gate return (0);
4617c478bd9Sstevel@tonic-gate }
4627c478bd9Sstevel@tonic-gate
4637c478bd9Sstevel@tonic-gate /*
4647c478bd9Sstevel@tonic-gate * Create the standard kernel statistics structure and attach it to
4657c478bd9Sstevel@tonic-gate * the current state structure. This can be called only after
4667c478bd9Sstevel@tonic-gate * assigning the unit number.
4677c478bd9Sstevel@tonic-gate */
4687c478bd9Sstevel@tonic-gate static void
create_kstats(sppp_ahdlc_t * state)4697c478bd9Sstevel@tonic-gate create_kstats(sppp_ahdlc_t *state)
4707c478bd9Sstevel@tonic-gate {
4717c478bd9Sstevel@tonic-gate kstat_t *ksp;
4727c478bd9Sstevel@tonic-gate char unitname[KSTAT_STRLEN];
4737c478bd9Sstevel@tonic-gate int nstat, i;
4747c478bd9Sstevel@tonic-gate kstat_named_t *knt;
4757c478bd9Sstevel@tonic-gate
4767c478bd9Sstevel@tonic-gate nstat = sizeof (state->sa_kstats) / sizeof (kstat_named_t);
4777c478bd9Sstevel@tonic-gate knt = (kstat_named_t *)&state->sa_kstats;
4787c478bd9Sstevel@tonic-gate for (i = 0; i < nstat; i++, knt++) {
4797c478bd9Sstevel@tonic-gate #ifdef DEBUG
4807c478bd9Sstevel@tonic-gate /* Just in case I do something silly here. */
4817c478bd9Sstevel@tonic-gate if (i >= sizeof (kstat_names) / sizeof (kstat_names[0]))
4827c478bd9Sstevel@tonic-gate (void) sprintf(knt->name, "unknown%d", i);
4837c478bd9Sstevel@tonic-gate else
4847c478bd9Sstevel@tonic-gate #endif
4857c478bd9Sstevel@tonic-gate (void) strncpy(knt->name, kstat_names[i],
4867c478bd9Sstevel@tonic-gate sizeof (knt->name));
4877c478bd9Sstevel@tonic-gate knt->data_type = KSTAT_DATA_UINT32;
4887c478bd9Sstevel@tonic-gate }
4897c478bd9Sstevel@tonic-gate /*
4907c478bd9Sstevel@tonic-gate * sprintf is known to be safe here because KSTAT_STRLEN is
4917c478bd9Sstevel@tonic-gate * 31, the maximum module name length is 8, and the maximum
4927c478bd9Sstevel@tonic-gate * string length from %d is 11. This was once snprintf, but
4937c478bd9Sstevel@tonic-gate * that's not backward-compatible with Solaris 2.6.
4947c478bd9Sstevel@tonic-gate */
495*002c70ffScarlsonj (void) sprintf(unitname, "%s" "%d", AHDLC_MOD_NAME, state->sa_unit);
4967c478bd9Sstevel@tonic-gate ksp = kstat_create(AHDLC_MOD_NAME, state->sa_unit, unitname, "net",
4977c478bd9Sstevel@tonic-gate KSTAT_TYPE_NAMED, nstat, KSTAT_FLAG_VIRTUAL);
4987c478bd9Sstevel@tonic-gate if (ksp != NULL) {
4997c478bd9Sstevel@tonic-gate ksp->ks_data = (void *)&state->sa_kstats;
5007c478bd9Sstevel@tonic-gate kstat_install(ksp);
5017c478bd9Sstevel@tonic-gate }
5027c478bd9Sstevel@tonic-gate state->sa_ksp = ksp;
5037c478bd9Sstevel@tonic-gate #ifdef REPORT_CRC_TYPE
5047c478bd9Sstevel@tonic-gate KSET(pks_outcrctype, 16);
5057c478bd9Sstevel@tonic-gate KSET(pks_incrctype, 16);
5067c478bd9Sstevel@tonic-gate #endif
5077c478bd9Sstevel@tonic-gate }
5087c478bd9Sstevel@tonic-gate
5097c478bd9Sstevel@tonic-gate /*
5107c478bd9Sstevel@tonic-gate * spppasyn_inner_ioctl
5117c478bd9Sstevel@tonic-gate *
5127c478bd9Sstevel@tonic-gate * MT-Perimeters:
5137c478bd9Sstevel@tonic-gate * exclusive inner
5147c478bd9Sstevel@tonic-gate *
5157c478bd9Sstevel@tonic-gate * Handle state-affecting ioctls.
5167c478bd9Sstevel@tonic-gate */
5177c478bd9Sstevel@tonic-gate static void
spppasyn_inner_ioctl(queue_t * q,mblk_t * mp)5187c478bd9Sstevel@tonic-gate spppasyn_inner_ioctl(queue_t *q, mblk_t *mp)
5197c478bd9Sstevel@tonic-gate {
5207c478bd9Sstevel@tonic-gate sppp_ahdlc_t *state;
5217c478bd9Sstevel@tonic-gate struct iocblk *iop;
5227c478bd9Sstevel@tonic-gate int error;
5237c478bd9Sstevel@tonic-gate int flagval;
5247c478bd9Sstevel@tonic-gate int len;
5257c478bd9Sstevel@tonic-gate uint32_t mux_flags;
5267c478bd9Sstevel@tonic-gate uint32_t mask;
5277c478bd9Sstevel@tonic-gate int flagmask;
5287c478bd9Sstevel@tonic-gate
5297c478bd9Sstevel@tonic-gate ASSERT(q != NULL && mp != NULL);
5307c478bd9Sstevel@tonic-gate state = (sppp_ahdlc_t *)q->q_ptr;
5317c478bd9Sstevel@tonic-gate iop = (struct iocblk *)mp->b_rptr;
5327c478bd9Sstevel@tonic-gate ASSERT(state != NULL && iop != NULL);
5337c478bd9Sstevel@tonic-gate
5347c478bd9Sstevel@tonic-gate error = EINVAL;
5357c478bd9Sstevel@tonic-gate len = 0;
5367c478bd9Sstevel@tonic-gate
5377c478bd9Sstevel@tonic-gate switch (iop->ioc_cmd) {
5387c478bd9Sstevel@tonic-gate case PPPIO_XFCS:
5397c478bd9Sstevel@tonic-gate /* Check for valid option length */
5407c478bd9Sstevel@tonic-gate if (iop->ioc_count != sizeof (uint32_t) || mp->b_cont == NULL)
5417c478bd9Sstevel@tonic-gate break;
5427c478bd9Sstevel@tonic-gate
5437c478bd9Sstevel@tonic-gate /* Grab flag value */
5447c478bd9Sstevel@tonic-gate flagval = *(uint32_t *)mp->b_cont->b_rptr;
5457c478bd9Sstevel@tonic-gate if (flagval < PPPFCS_16 || flagval > PPPFCS_NONE)
5467c478bd9Sstevel@tonic-gate break;
5477c478bd9Sstevel@tonic-gate state->sa_flags &= ~SAF_XMITCRC32 & ~SAF_XMITCRCNONE;
5487c478bd9Sstevel@tonic-gate if (flagval == PPPFCS_32) {
5497c478bd9Sstevel@tonic-gate #ifdef REPORT_CRC_TYPE
5507c478bd9Sstevel@tonic-gate KSET(pks_outcrctype, 32);
5517c478bd9Sstevel@tonic-gate #endif
5527c478bd9Sstevel@tonic-gate state->sa_flags |= SAF_XMITCRC32;
5537c478bd9Sstevel@tonic-gate } else if (flagval == PPPFCS_NONE) {
5547c478bd9Sstevel@tonic-gate #ifdef REPORT_CRC_TYPE
5557c478bd9Sstevel@tonic-gate KSET(pks_outcrctype, 0);
5567c478bd9Sstevel@tonic-gate #endif
5577c478bd9Sstevel@tonic-gate state->sa_flags |= SAF_XMITCRCNONE;
5587c478bd9Sstevel@tonic-gate }
5597c478bd9Sstevel@tonic-gate #ifdef REPORT_CRC_TYPE
5607c478bd9Sstevel@tonic-gate else {
5617c478bd9Sstevel@tonic-gate KSET(pks_outcrctype, 16);
5627c478bd9Sstevel@tonic-gate }
5637c478bd9Sstevel@tonic-gate #endif
5647c478bd9Sstevel@tonic-gate
5657c478bd9Sstevel@tonic-gate /* Return success */
5667c478bd9Sstevel@tonic-gate error = 0;
5677c478bd9Sstevel@tonic-gate break;
5687c478bd9Sstevel@tonic-gate
5697c478bd9Sstevel@tonic-gate case PPPIO_RFCS:
5707c478bd9Sstevel@tonic-gate /* Check for valid option length */
5717c478bd9Sstevel@tonic-gate if (iop->ioc_count != sizeof (uint32_t) || mp->b_cont == NULL)
5727c478bd9Sstevel@tonic-gate break;
5737c478bd9Sstevel@tonic-gate
5747c478bd9Sstevel@tonic-gate /* Grab flag value */
5757c478bd9Sstevel@tonic-gate flagval = *(uint32_t *)mp->b_cont->b_rptr;
5767c478bd9Sstevel@tonic-gate if (flagval < PPPFCS_16 || flagval > PPPFCS_NONE)
5777c478bd9Sstevel@tonic-gate break;
5787c478bd9Sstevel@tonic-gate state->sa_flags &= ~SAF_RECVCRC32 & ~SAF_RECVCRCNONE;
5797c478bd9Sstevel@tonic-gate if (flagval == PPPFCS_32) {
5807c478bd9Sstevel@tonic-gate #ifdef REPORT_CRC_TYPE
5817c478bd9Sstevel@tonic-gate KSET(pks_incrctype, 32);
5827c478bd9Sstevel@tonic-gate #endif
5837c478bd9Sstevel@tonic-gate state->sa_flags |= SAF_RECVCRC32;
5847c478bd9Sstevel@tonic-gate } else if (flagval == PPPFCS_NONE) {
5857c478bd9Sstevel@tonic-gate #ifdef REPORT_CRC_TYPE
5867c478bd9Sstevel@tonic-gate KSET(pks_incrctype, 0);
5877c478bd9Sstevel@tonic-gate #endif
5887c478bd9Sstevel@tonic-gate state->sa_flags |= SAF_RECVCRCNONE;
5897c478bd9Sstevel@tonic-gate }
5907c478bd9Sstevel@tonic-gate #ifdef REPORT_CRC_TYPE
5917c478bd9Sstevel@tonic-gate else {
5927c478bd9Sstevel@tonic-gate KSET(pks_incrctype, 16);
5937c478bd9Sstevel@tonic-gate }
5947c478bd9Sstevel@tonic-gate #endif
5957c478bd9Sstevel@tonic-gate
5967c478bd9Sstevel@tonic-gate /* Return success */
5977c478bd9Sstevel@tonic-gate error = 0;
5987c478bd9Sstevel@tonic-gate break;
5997c478bd9Sstevel@tonic-gate
6007c478bd9Sstevel@tonic-gate case PPPIO_XACCM:
6017c478bd9Sstevel@tonic-gate /* Check for valid asyncmap length */
6027c478bd9Sstevel@tonic-gate if (iop->ioc_count < sizeof (uint32_t) ||
6037c478bd9Sstevel@tonic-gate iop->ioc_count > sizeof (ext_accm) ||
6047c478bd9Sstevel@tonic-gate mp->b_cont == NULL)
6057c478bd9Sstevel@tonic-gate break;
6067c478bd9Sstevel@tonic-gate
6077c478bd9Sstevel@tonic-gate /* Copy user's asyncmap into our state structure. */
6087c478bd9Sstevel@tonic-gate bcopy((caddr_t)mp->b_cont->b_rptr,
6097c478bd9Sstevel@tonic-gate (caddr_t)state->sa_xaccm, iop->ioc_count);
6107c478bd9Sstevel@tonic-gate
6117c478bd9Sstevel@tonic-gate state->sa_xaccm[2] &= ~0x40000000; /* don't escape 0x5e */
6127c478bd9Sstevel@tonic-gate state->sa_xaccm[3] |= 0x60000000; /* escape 0x7d, 0x7e */
6137c478bd9Sstevel@tonic-gate
6147c478bd9Sstevel@tonic-gate error = 0;
6157c478bd9Sstevel@tonic-gate break;
6167c478bd9Sstevel@tonic-gate
6177c478bd9Sstevel@tonic-gate case PPPIO_RACCM:
6187c478bd9Sstevel@tonic-gate /* Check for valid asyncmap length (only ctrl chars) */
6197c478bd9Sstevel@tonic-gate if (iop->ioc_count != sizeof (uint32_t) ||
6207c478bd9Sstevel@tonic-gate mp->b_cont == NULL)
6217c478bd9Sstevel@tonic-gate break;
6227c478bd9Sstevel@tonic-gate
6237c478bd9Sstevel@tonic-gate state->sa_raccm = *(uint32_t *)mp->b_cont->b_rptr;
6247c478bd9Sstevel@tonic-gate
6257c478bd9Sstevel@tonic-gate error = 0;
6267c478bd9Sstevel@tonic-gate break;
6277c478bd9Sstevel@tonic-gate
6287c478bd9Sstevel@tonic-gate case PPPIO_LASTMOD:
6297c478bd9Sstevel@tonic-gate /* We already know this. */
6307c478bd9Sstevel@tonic-gate state->sa_flags |= SAF_LASTMOD;
6317c478bd9Sstevel@tonic-gate error = 0;
6327c478bd9Sstevel@tonic-gate break;
6337c478bd9Sstevel@tonic-gate
6347c478bd9Sstevel@tonic-gate case PPPIO_MUX:
6357c478bd9Sstevel@tonic-gate /* set the compression flags */
6367c478bd9Sstevel@tonic-gate if (iop->ioc_count != 2 * sizeof (uint32_t) ||
6377c478bd9Sstevel@tonic-gate mp->b_cont == NULL)
6387c478bd9Sstevel@tonic-gate break;
6397c478bd9Sstevel@tonic-gate
6407c478bd9Sstevel@tonic-gate /* set the mux flags */
6417c478bd9Sstevel@tonic-gate mux_flags = ((uint32_t *)mp->b_cont->b_rptr)[0];
6427c478bd9Sstevel@tonic-gate mask = ((uint32_t *)mp->b_cont->b_rptr)[1];
6437c478bd9Sstevel@tonic-gate if (mux_flags != 0)
6447c478bd9Sstevel@tonic-gate state->sa_flags = (state->sa_flags & ~mask) | (mask);
6457c478bd9Sstevel@tonic-gate
6467c478bd9Sstevel@tonic-gate /* set the multiplexing timer value */
6477c478bd9Sstevel@tonic-gate if (mask & R_MUXMASK)
6487c478bd9Sstevel@tonic-gate state->sa_timeout_usec = mux_flags;
6497c478bd9Sstevel@tonic-gate
6507c478bd9Sstevel@tonic-gate error = 0;
6517c478bd9Sstevel@tonic-gate break;
6527c478bd9Sstevel@tonic-gate
6537c478bd9Sstevel@tonic-gate case PPPIO_CFLAGS:
6547c478bd9Sstevel@tonic-gate if (iop->ioc_count != 2 * sizeof (uint32_t) ||
6557c478bd9Sstevel@tonic-gate mp->b_cont == NULL)
6567c478bd9Sstevel@tonic-gate break;
6577c478bd9Sstevel@tonic-gate
6587c478bd9Sstevel@tonic-gate flagval = (((uint32_t *)mp->b_cont->b_rptr)[0] << 20) &
6597c478bd9Sstevel@tonic-gate (SAF_RDECOMP_PROT | SAF_RDECOMP_AC | SAF_XCOMP_PROT |
6607c478bd9Sstevel@tonic-gate SAF_XCOMP_AC);
6617c478bd9Sstevel@tonic-gate flagmask = (((uint32_t *)mp->b_cont->b_rptr)[1] << 20) &
6627c478bd9Sstevel@tonic-gate (SAF_RDECOMP_PROT | SAF_RDECOMP_AC | SAF_XCOMP_PROT |
6637c478bd9Sstevel@tonic-gate SAF_XCOMP_AC);
6647c478bd9Sstevel@tonic-gate state->sa_flags = flagval | (state->sa_flags & ~flagmask);
6657c478bd9Sstevel@tonic-gate *(uint32_t *)mp->b_cont->b_rptr = state->sa_flags >> 20;
6667c478bd9Sstevel@tonic-gate len = sizeof (uint32_t);
6677c478bd9Sstevel@tonic-gate error = 0;
6687c478bd9Sstevel@tonic-gate break;
6697c478bd9Sstevel@tonic-gate
6707c478bd9Sstevel@tonic-gate case PPPIO_DEBUG:
6717c478bd9Sstevel@tonic-gate if (iop->ioc_count != sizeof (uint32_t) || mp->b_cont == NULL)
6727c478bd9Sstevel@tonic-gate break;
6737c478bd9Sstevel@tonic-gate
6747c478bd9Sstevel@tonic-gate flagval = *(uint32_t *)mp->b_cont->b_rptr;
6757c478bd9Sstevel@tonic-gate if (flagval != PPPDBG_LOG + PPPDBG_AHDLC) {
6767c478bd9Sstevel@tonic-gate putnext(q, mp);
6777c478bd9Sstevel@tonic-gate return;
6787c478bd9Sstevel@tonic-gate }
6797c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, AHDLC_MOD_NAME "%d: debug log enabled\n",
6807c478bd9Sstevel@tonic-gate state->sa_unit);
6817c478bd9Sstevel@tonic-gate state->sa_flags |= SAF_XMITDUMP | SAF_RECVDUMP;
6827c478bd9Sstevel@tonic-gate error = 0;
6837c478bd9Sstevel@tonic-gate break;
6847c478bd9Sstevel@tonic-gate }
6857c478bd9Sstevel@tonic-gate
6867c478bd9Sstevel@tonic-gate if (error == 0) {
6877c478bd9Sstevel@tonic-gate /* Success; tell the user */
6887c478bd9Sstevel@tonic-gate if (mp->b_cont == NULL)
6897c478bd9Sstevel@tonic-gate len = 0;
6907c478bd9Sstevel@tonic-gate else
6917c478bd9Sstevel@tonic-gate mp->b_cont->b_wptr = mp->b_cont->b_rptr + len;
6927c478bd9Sstevel@tonic-gate miocack(q, mp, len, 0);
6937c478bd9Sstevel@tonic-gate } else {
6947c478bd9Sstevel@tonic-gate /* Failure; send error back upstream. */
6957c478bd9Sstevel@tonic-gate KINCR(pks_ioctlserr);
6967c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, error);
6977c478bd9Sstevel@tonic-gate }
6987c478bd9Sstevel@tonic-gate }
6997c478bd9Sstevel@tonic-gate
7007c478bd9Sstevel@tonic-gate /*
7017c478bd9Sstevel@tonic-gate * spppasyn_inner_mctl
7027c478bd9Sstevel@tonic-gate *
7037c478bd9Sstevel@tonic-gate * MT-Perimeters:
7047c478bd9Sstevel@tonic-gate * exclusive inner
7057c478bd9Sstevel@tonic-gate *
7067c478bd9Sstevel@tonic-gate * Handle state-affecting M_CTL messages.
7077c478bd9Sstevel@tonic-gate */
7087c478bd9Sstevel@tonic-gate static void
spppasyn_inner_mctl(queue_t * q,mblk_t * mp)7097c478bd9Sstevel@tonic-gate spppasyn_inner_mctl(queue_t *q, mblk_t *mp)
7107c478bd9Sstevel@tonic-gate {
7117c478bd9Sstevel@tonic-gate sppp_ahdlc_t *state;
7127c478bd9Sstevel@tonic-gate int msglen;
7137c478bd9Sstevel@tonic-gate int error;
7147c478bd9Sstevel@tonic-gate
7157c478bd9Sstevel@tonic-gate ASSERT(q != NULL && mp != NULL);
7167c478bd9Sstevel@tonic-gate state = (sppp_ahdlc_t *)q->q_ptr;
7177c478bd9Sstevel@tonic-gate ASSERT(state != NULL);
7187c478bd9Sstevel@tonic-gate
7197c478bd9Sstevel@tonic-gate msglen = MBLKL(mp);
7207c478bd9Sstevel@tonic-gate error = 0;
7217c478bd9Sstevel@tonic-gate switch (*mp->b_rptr) {
7227c478bd9Sstevel@tonic-gate case PPPCTL_MTU:
7237c478bd9Sstevel@tonic-gate /* Just ignore the MTU */
7247c478bd9Sstevel@tonic-gate break;
7257c478bd9Sstevel@tonic-gate
7267c478bd9Sstevel@tonic-gate case PPPCTL_MRU:
7277c478bd9Sstevel@tonic-gate if (msglen != 4)
7287c478bd9Sstevel@tonic-gate error = EINVAL;
7297c478bd9Sstevel@tonic-gate else
7307c478bd9Sstevel@tonic-gate state->sa_mru =
7317c478bd9Sstevel@tonic-gate ((ushort_t *)mp->b_rptr)[1];
7327c478bd9Sstevel@tonic-gate break;
7337c478bd9Sstevel@tonic-gate
7347c478bd9Sstevel@tonic-gate case PPPCTL_UNIT:
7357c478bd9Sstevel@tonic-gate if (state->sa_ksp != NULL) {
7367c478bd9Sstevel@tonic-gate error = EINVAL;
7377c478bd9Sstevel@tonic-gate break;
7387c478bd9Sstevel@tonic-gate }
7397c478bd9Sstevel@tonic-gate if (msglen == 2)
7407c478bd9Sstevel@tonic-gate state->sa_unit = mp->b_rptr[1];
7417c478bd9Sstevel@tonic-gate else if (msglen == 8)
7427c478bd9Sstevel@tonic-gate state->sa_unit =
7437c478bd9Sstevel@tonic-gate ((uint32_t *)mp->b_rptr)[1];
7447c478bd9Sstevel@tonic-gate else
7457c478bd9Sstevel@tonic-gate error = EINVAL;
7467c478bd9Sstevel@tonic-gate if (error == 0 && state->sa_ksp == NULL)
7477c478bd9Sstevel@tonic-gate create_kstats(state);
7487c478bd9Sstevel@tonic-gate break;
7497c478bd9Sstevel@tonic-gate }
7507c478bd9Sstevel@tonic-gate
7517c478bd9Sstevel@tonic-gate if (error > 0) {
7527c478bd9Sstevel@tonic-gate KINCR(pks_ctlserr);
7537c478bd9Sstevel@tonic-gate }
7547c478bd9Sstevel@tonic-gate if (state->sa_flags & SAF_LASTMOD) {
7557c478bd9Sstevel@tonic-gate freemsg(mp);
7567c478bd9Sstevel@tonic-gate } else {
7577c478bd9Sstevel@tonic-gate KINCR(pks_ctlsfwd);
7587c478bd9Sstevel@tonic-gate putnext(q, mp);
7597c478bd9Sstevel@tonic-gate }
7607c478bd9Sstevel@tonic-gate }
7617c478bd9Sstevel@tonic-gate
7627c478bd9Sstevel@tonic-gate /*
7637c478bd9Sstevel@tonic-gate * spppasyn_wput()
7647c478bd9Sstevel@tonic-gate *
7657c478bd9Sstevel@tonic-gate * MT-Perimeters:
7667c478bd9Sstevel@tonic-gate * exclusive inner.
7677c478bd9Sstevel@tonic-gate *
7687c478bd9Sstevel@tonic-gate * Write side put routine. This called by the modules above us (likely to
7697c478bd9Sstevel@tonic-gate * be the compression module) to transmit data or pass along ioctls.
7707c478bd9Sstevel@tonic-gate */
7717c478bd9Sstevel@tonic-gate static int
spppasyn_wput(queue_t * q,mblk_t * mp)7727c478bd9Sstevel@tonic-gate spppasyn_wput(queue_t *q, mblk_t *mp)
7737c478bd9Sstevel@tonic-gate {
7747c478bd9Sstevel@tonic-gate sppp_ahdlc_t *state;
7757c478bd9Sstevel@tonic-gate struct iocblk *iop;
7767c478bd9Sstevel@tonic-gate int error;
7777c478bd9Sstevel@tonic-gate mblk_t *np;
7787c478bd9Sstevel@tonic-gate struct ppp_stats64 *psp;
7797c478bd9Sstevel@tonic-gate int msglen;
7807c478bd9Sstevel@tonic-gate
7817c478bd9Sstevel@tonic-gate ASSERT(q != NULL && mp != NULL);
7827c478bd9Sstevel@tonic-gate state = (sppp_ahdlc_t *)q->q_ptr;
7837c478bd9Sstevel@tonic-gate ASSERT(state != NULL);
7847c478bd9Sstevel@tonic-gate
7857c478bd9Sstevel@tonic-gate switch (MTYPE(mp)) {
7867c478bd9Sstevel@tonic-gate
7877c478bd9Sstevel@tonic-gate case M_DATA:
7887c478bd9Sstevel@tonic-gate /*
7897c478bd9Sstevel@tonic-gate * A data packet - do character-stuffing and FCS, and
7907c478bd9Sstevel@tonic-gate * send it onwards. The blocks are freed as we go.
7917c478bd9Sstevel@tonic-gate */
7927c478bd9Sstevel@tonic-gate if (IS_XMUX_ENABLED(state))
7937c478bd9Sstevel@tonic-gate mp = spppasyn_muxencode(q, mp);
7947c478bd9Sstevel@tonic-gate else
7957c478bd9Sstevel@tonic-gate mp = ahdlc_encode(q, mp);
7967c478bd9Sstevel@tonic-gate if (mp != NULL)
7977c478bd9Sstevel@tonic-gate putnext(q, mp);
7987c478bd9Sstevel@tonic-gate break;
7997c478bd9Sstevel@tonic-gate
8007c478bd9Sstevel@tonic-gate case M_IOCTL:
8017c478bd9Sstevel@tonic-gate
8027c478bd9Sstevel@tonic-gate KINCR(pks_ioctls);
8037c478bd9Sstevel@tonic-gate iop = (struct iocblk *)mp->b_rptr;
8047c478bd9Sstevel@tonic-gate
8057c478bd9Sstevel@tonic-gate msglen = 0;
8067c478bd9Sstevel@tonic-gate
8077c478bd9Sstevel@tonic-gate switch (iop->ioc_cmd) {
8087c478bd9Sstevel@tonic-gate case PPPIO_XFCS:
8097c478bd9Sstevel@tonic-gate case PPPIO_RFCS:
8107c478bd9Sstevel@tonic-gate case PPPIO_XACCM:
8117c478bd9Sstevel@tonic-gate case PPPIO_RACCM:
8127c478bd9Sstevel@tonic-gate case PPPIO_LASTMOD:
8137c478bd9Sstevel@tonic-gate case PPPIO_DEBUG:
8147c478bd9Sstevel@tonic-gate case PPPIO_MUX:
8157c478bd9Sstevel@tonic-gate case PPPIO_CFLAGS:
8167c478bd9Sstevel@tonic-gate spppasyn_inner_ioctl(q, mp);
8177c478bd9Sstevel@tonic-gate return (0);
8187c478bd9Sstevel@tonic-gate
8197c478bd9Sstevel@tonic-gate case PPPIO_GCLEAN:
8207c478bd9Sstevel@tonic-gate np = allocb(sizeof (uint32_t), BPRI_HI);
8217c478bd9Sstevel@tonic-gate if (np == NULL) {
8227c478bd9Sstevel@tonic-gate error = ENOSR;
8237c478bd9Sstevel@tonic-gate break;
8247c478bd9Sstevel@tonic-gate }
8257c478bd9Sstevel@tonic-gate if (mp->b_cont != NULL) {
8267c478bd9Sstevel@tonic-gate freemsg(mp->b_cont);
8277c478bd9Sstevel@tonic-gate }
8287c478bd9Sstevel@tonic-gate mp->b_cont = np;
8297c478bd9Sstevel@tonic-gate
8307c478bd9Sstevel@tonic-gate *(uint32_t *)np->b_wptr = state->sa_flags & RCV_FLAGS;
8317c478bd9Sstevel@tonic-gate
8327c478bd9Sstevel@tonic-gate msglen = sizeof (uint32_t);
8337c478bd9Sstevel@tonic-gate np->b_wptr += msglen;
8347c478bd9Sstevel@tonic-gate error = 0;
8357c478bd9Sstevel@tonic-gate break;
8367c478bd9Sstevel@tonic-gate
8377c478bd9Sstevel@tonic-gate case PPPIO_GETSTAT:
8387c478bd9Sstevel@tonic-gate error = EINVAL;
8397c478bd9Sstevel@tonic-gate break;
8407c478bd9Sstevel@tonic-gate
8417c478bd9Sstevel@tonic-gate case PPPIO_GETSTAT64:
8427c478bd9Sstevel@tonic-gate np = allocb(sizeof (*psp), BPRI_HI);
8437c478bd9Sstevel@tonic-gate if (np == NULL) {
8447c478bd9Sstevel@tonic-gate error = ENOSR;
8457c478bd9Sstevel@tonic-gate break;
8467c478bd9Sstevel@tonic-gate }
8477c478bd9Sstevel@tonic-gate if (mp->b_cont != NULL) {
8487c478bd9Sstevel@tonic-gate freemsg(mp->b_cont);
8497c478bd9Sstevel@tonic-gate }
8507c478bd9Sstevel@tonic-gate mp->b_cont = np;
8517c478bd9Sstevel@tonic-gate
8527c478bd9Sstevel@tonic-gate psp = (struct ppp_stats64 *)np->b_wptr;
8537c478bd9Sstevel@tonic-gate bzero((caddr_t)psp, sizeof (*psp));
8547c478bd9Sstevel@tonic-gate psp->p = state->sa_stats;
8557c478bd9Sstevel@tonic-gate
8567c478bd9Sstevel@tonic-gate msglen = sizeof (*psp);
8577c478bd9Sstevel@tonic-gate np->b_wptr += msglen;
8587c478bd9Sstevel@tonic-gate error = 0;
8597c478bd9Sstevel@tonic-gate break;
8607c478bd9Sstevel@tonic-gate
8617c478bd9Sstevel@tonic-gate case PPPIO_GTYPE:
8627c478bd9Sstevel@tonic-gate np = allocb(sizeof (uint32_t), BPRI_HI);
8637c478bd9Sstevel@tonic-gate if (np == NULL) {
8647c478bd9Sstevel@tonic-gate error = ENOSR;
8657c478bd9Sstevel@tonic-gate break;
8667c478bd9Sstevel@tonic-gate }
8677c478bd9Sstevel@tonic-gate if (mp->b_cont != NULL) {
8687c478bd9Sstevel@tonic-gate freemsg(mp->b_cont);
8697c478bd9Sstevel@tonic-gate }
8707c478bd9Sstevel@tonic-gate mp->b_cont = np;
8717c478bd9Sstevel@tonic-gate
8727c478bd9Sstevel@tonic-gate *(uint32_t *)np->b_wptr = PPPTYP_AHDLC;
8737c478bd9Sstevel@tonic-gate
8747c478bd9Sstevel@tonic-gate msglen = sizeof (uint32_t);
8757c478bd9Sstevel@tonic-gate np->b_wptr += msglen;
8767c478bd9Sstevel@tonic-gate error = 0;
8777c478bd9Sstevel@tonic-gate break;
8787c478bd9Sstevel@tonic-gate
8797c478bd9Sstevel@tonic-gate default:
8807c478bd9Sstevel@tonic-gate /* Unknown ioctl -- forward along */
8817c478bd9Sstevel@tonic-gate KINCR(pks_ioctlsfwd);
8827c478bd9Sstevel@tonic-gate putnext(q, mp);
8837c478bd9Sstevel@tonic-gate return (0);
8847c478bd9Sstevel@tonic-gate }
8857c478bd9Sstevel@tonic-gate
8867c478bd9Sstevel@tonic-gate if (error == 0) {
8877c478bd9Sstevel@tonic-gate /* Success; tell the user */
8887c478bd9Sstevel@tonic-gate miocack(q, mp, msglen, 0);
8897c478bd9Sstevel@tonic-gate } else {
8907c478bd9Sstevel@tonic-gate /* Failure; send error back upstream. */
8917c478bd9Sstevel@tonic-gate KINCR(pks_ioctlserr);
8927c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, error);
8937c478bd9Sstevel@tonic-gate }
8947c478bd9Sstevel@tonic-gate
8957c478bd9Sstevel@tonic-gate break;
8967c478bd9Sstevel@tonic-gate
8977c478bd9Sstevel@tonic-gate case M_CTL:
8987c478bd9Sstevel@tonic-gate KINCR(pks_ctls);
8997c478bd9Sstevel@tonic-gate spppasyn_inner_mctl(q, mp);
9007c478bd9Sstevel@tonic-gate break;
9017c478bd9Sstevel@tonic-gate
9027c478bd9Sstevel@tonic-gate default:
9037c478bd9Sstevel@tonic-gate if (state->sa_flags & (SAF_XMITDUMP|SAF_RECVDUMP))
9047c478bd9Sstevel@tonic-gate cmn_err(CE_CONT,
9057c478bd9Sstevel@tonic-gate "spppasyn_wpur: unknown buffer type %d",
9067c478bd9Sstevel@tonic-gate MTYPE(mp));
9077c478bd9Sstevel@tonic-gate KINCR(pks_unknownwrs);
9087c478bd9Sstevel@tonic-gate putnext(q, mp);
9097c478bd9Sstevel@tonic-gate break;
9107c478bd9Sstevel@tonic-gate }
9117c478bd9Sstevel@tonic-gate
9127c478bd9Sstevel@tonic-gate return (0);
9137c478bd9Sstevel@tonic-gate }
9147c478bd9Sstevel@tonic-gate
9157c478bd9Sstevel@tonic-gate /*
9167c478bd9Sstevel@tonic-gate * spppasyn_rput()
9177c478bd9Sstevel@tonic-gate *
9187c478bd9Sstevel@tonic-gate * MT-Perimeters:
9197c478bd9Sstevel@tonic-gate * exclusive inner.
9207c478bd9Sstevel@tonic-gate *
9217c478bd9Sstevel@tonic-gate * Read side put routine. This is called by the async serial driver
9227c478bd9Sstevel@tonic-gate * below us to handle received data and returned signals (like
9237c478bd9Sstevel@tonic-gate * hang-up).
9247c478bd9Sstevel@tonic-gate */
9257c478bd9Sstevel@tonic-gate static int
spppasyn_rput(queue_t * q,mblk_t * mp)9267c478bd9Sstevel@tonic-gate spppasyn_rput(queue_t *q, mblk_t *mp)
9277c478bd9Sstevel@tonic-gate {
9287c478bd9Sstevel@tonic-gate sppp_ahdlc_t *state;
9297c478bd9Sstevel@tonic-gate mblk_t *mpnext;
9307c478bd9Sstevel@tonic-gate
9317c478bd9Sstevel@tonic-gate ASSERT(q != NULL && mp != NULL);
9327c478bd9Sstevel@tonic-gate state = (sppp_ahdlc_t *)q->q_ptr;
9337c478bd9Sstevel@tonic-gate ASSERT(state != NULL);
9347c478bd9Sstevel@tonic-gate
9357c478bd9Sstevel@tonic-gate switch (MTYPE(mp)) {
9367c478bd9Sstevel@tonic-gate
9377c478bd9Sstevel@tonic-gate case M_DATA:
9387c478bd9Sstevel@tonic-gate /* Note -- decoder frees the buffers */
9397c478bd9Sstevel@tonic-gate mp = ahdlc_decode(q, mp);
9407c478bd9Sstevel@tonic-gate while (mp != NULL) {
9417c478bd9Sstevel@tonic-gate mpnext = mp->b_next;
9427c478bd9Sstevel@tonic-gate mp->b_next = NULL;
9437c478bd9Sstevel@tonic-gate putnext(q, mp);
9447c478bd9Sstevel@tonic-gate mp = mpnext;
9457c478bd9Sstevel@tonic-gate }
9467c478bd9Sstevel@tonic-gate break;
9477c478bd9Sstevel@tonic-gate
9487c478bd9Sstevel@tonic-gate case M_HANGUP:
9497c478bd9Sstevel@tonic-gate KINCR(pks_hangups);
9507c478bd9Sstevel@tonic-gate state->sa_flags |= SAF_IFLUSH;
9517c478bd9Sstevel@tonic-gate putnext(q, mp);
9527c478bd9Sstevel@tonic-gate break;
9537c478bd9Sstevel@tonic-gate
9547c478bd9Sstevel@tonic-gate default:
9557c478bd9Sstevel@tonic-gate if (state->sa_flags & (SAF_XMITDUMP|SAF_RECVDUMP)) {
9567c478bd9Sstevel@tonic-gate if (MTYPE(mp) == M_IOCTL)
9577c478bd9Sstevel@tonic-gate cmn_err(CE_CONT,
9587c478bd9Sstevel@tonic-gate "spppasyn_rput: unexpected ioctl %X",
9597c478bd9Sstevel@tonic-gate ((struct iocblk *)mp->b_rptr)->ioc_cmd);
9607c478bd9Sstevel@tonic-gate else
9617c478bd9Sstevel@tonic-gate cmn_err(CE_CONT,
9627c478bd9Sstevel@tonic-gate "spppasyn_rput: unknown buffer type %d",
9637c478bd9Sstevel@tonic-gate MTYPE(mp));
9647c478bd9Sstevel@tonic-gate }
9657c478bd9Sstevel@tonic-gate KINCR(pks_unknownrds);
9667c478bd9Sstevel@tonic-gate putnext(q, mp);
9677c478bd9Sstevel@tonic-gate break;
9687c478bd9Sstevel@tonic-gate }
9697c478bd9Sstevel@tonic-gate
9707c478bd9Sstevel@tonic-gate return (0);
9717c478bd9Sstevel@tonic-gate }
9727c478bd9Sstevel@tonic-gate
9737c478bd9Sstevel@tonic-gate /*
9747c478bd9Sstevel@tonic-gate * ahdlc_encode
9757c478bd9Sstevel@tonic-gate *
9767c478bd9Sstevel@tonic-gate * Perform asynchronous HDLC framing on a given buffer and transmit
9777c478bd9Sstevel@tonic-gate * the result. The state structure must be valid. The input buffers
9787c478bd9Sstevel@tonic-gate * are freed as we go.
9797c478bd9Sstevel@tonic-gate *
9807c478bd9Sstevel@tonic-gate * This function is called by wput and just encodes the data. Wput
9817c478bd9Sstevel@tonic-gate * then calls putnext directly. There's no service routine for this
9827c478bd9Sstevel@tonic-gate * module, so flow control is asserted by the module below us up to
9837c478bd9Sstevel@tonic-gate * our caller by the STREAMS framework. This is by design -- this
9847c478bd9Sstevel@tonic-gate * module does not queue anything so that other modules can make QoS
9857c478bd9Sstevel@tonic-gate * decisions.
9867c478bd9Sstevel@tonic-gate */
9877c478bd9Sstevel@tonic-gate static mblk_t *
ahdlc_encode(queue_t * q,mblk_t * mp)9887c478bd9Sstevel@tonic-gate ahdlc_encode(queue_t *q, mblk_t *mp)
9897c478bd9Sstevel@tonic-gate {
9907c478bd9Sstevel@tonic-gate sppp_ahdlc_t *state;
9917c478bd9Sstevel@tonic-gate uint32_t loc_xaccm[8];
9927c478bd9Sstevel@tonic-gate ushort_t fcs16;
9937c478bd9Sstevel@tonic-gate uint32_t fcs32;
9947c478bd9Sstevel@tonic-gate size_t msglen;
9957c478bd9Sstevel@tonic-gate size_t outmp_len;
9967c478bd9Sstevel@tonic-gate mblk_t *outmp;
9977c478bd9Sstevel@tonic-gate mblk_t *curout;
9987c478bd9Sstevel@tonic-gate mblk_t *tmp;
9997c478bd9Sstevel@tonic-gate uchar_t *ep;
10007c478bd9Sstevel@tonic-gate uchar_t *dp;
10017c478bd9Sstevel@tonic-gate uchar_t *tp;
10027c478bd9Sstevel@tonic-gate uchar_t *tpmax;
10037c478bd9Sstevel@tonic-gate #if defined(lint) || defined(_lint)
10047c478bd9Sstevel@tonic-gate uchar_t chr; /* lint likes this */
10057c478bd9Sstevel@tonic-gate #else
10067c478bd9Sstevel@tonic-gate int chr; /* not uchar_t; more efficient this way */
10077c478bd9Sstevel@tonic-gate /* with WorkShop compiler */
10087c478bd9Sstevel@tonic-gate #endif
10097c478bd9Sstevel@tonic-gate int is_lcp, is_ctrl;
10107c478bd9Sstevel@tonic-gate int code;
10117c478bd9Sstevel@tonic-gate hrtime_t hrtime;
10127c478bd9Sstevel@tonic-gate uint32_t flags; /* sampled copy of flags */
10137c478bd9Sstevel@tonic-gate
10147c478bd9Sstevel@tonic-gate state = (sppp_ahdlc_t *)q->q_ptr;
10157c478bd9Sstevel@tonic-gate
10167c478bd9Sstevel@tonic-gate /* Don't transmit anything obviously silly. */
10177c478bd9Sstevel@tonic-gate msglen = msgsize(mp);
10187c478bd9Sstevel@tonic-gate if (msglen < 4) {
10197c478bd9Sstevel@tonic-gate KINCR(pks_outrunts);
10207c478bd9Sstevel@tonic-gate freemsg(mp);
10217c478bd9Sstevel@tonic-gate (void) putnextctl1(RD(q), M_CTL, PPPCTL_OERROR);
10227c478bd9Sstevel@tonic-gate return (NULL);
10237c478bd9Sstevel@tonic-gate }
10247c478bd9Sstevel@tonic-gate
10257c478bd9Sstevel@tonic-gate /*
10267c478bd9Sstevel@tonic-gate * Allocate an output buffer just large enough for most cases.
10277c478bd9Sstevel@tonic-gate * Based on original work in the ppp-2.2 AIX PPP driver, we
10287c478bd9Sstevel@tonic-gate * estimate the output size as 1.25 * input message length
10297c478bd9Sstevel@tonic-gate * plus 16. If this turns out to be too small, then we'll
10307c478bd9Sstevel@tonic-gate * allocate exactly one additional buffer with two times the
10317c478bd9Sstevel@tonic-gate * remaining input length (the maximum that could possibly be
10327c478bd9Sstevel@tonic-gate * required).
10337c478bd9Sstevel@tonic-gate */
10347c478bd9Sstevel@tonic-gate outmp_len = msglen + (msglen >> 2) + 16;
10357c478bd9Sstevel@tonic-gate outmp = allocb(outmp_len, BPRI_MED);
10367c478bd9Sstevel@tonic-gate if (outmp == NULL)
10377c478bd9Sstevel@tonic-gate goto outallocfail;
10387c478bd9Sstevel@tonic-gate
10397c478bd9Sstevel@tonic-gate tp = outmp->b_wptr;
10407c478bd9Sstevel@tonic-gate
10417c478bd9Sstevel@tonic-gate /*
10427c478bd9Sstevel@tonic-gate * Check if our last transmit happened within FLAG_TIME, using
10437c478bd9Sstevel@tonic-gate * the system's hrtime.
10447c478bd9Sstevel@tonic-gate */
10457c478bd9Sstevel@tonic-gate hrtime = gethrtime();
10467c478bd9Sstevel@tonic-gate if (ABS(hrtime - state->sa_hrtime) > FLAG_TIME) {
10477c478bd9Sstevel@tonic-gate *tp++ = PPP_FLAG;
10487c478bd9Sstevel@tonic-gate }
10497c478bd9Sstevel@tonic-gate state->sa_hrtime = hrtime;
10507c478bd9Sstevel@tonic-gate bcopy((caddr_t)state->sa_xaccm, (caddr_t)loc_xaccm, sizeof (loc_xaccm));
10517c478bd9Sstevel@tonic-gate flags = state->sa_flags;
10527c478bd9Sstevel@tonic-gate
10537c478bd9Sstevel@tonic-gate /*
10547c478bd9Sstevel@tonic-gate * LCP messages must be sent using the default escaping
10557c478bd9Sstevel@tonic-gate * (ACCM). We bend this rule a little to allow LCP
10567c478bd9Sstevel@tonic-gate * Echo-Request through with the negotiated escaping so that
10577c478bd9Sstevel@tonic-gate * we can detect bad negotiated ACCM values. If the ACCM is
10587c478bd9Sstevel@tonic-gate * bad, echos will fail and take down the link.
10597c478bd9Sstevel@tonic-gate */
10607c478bd9Sstevel@tonic-gate is_lcp = is_ctrl = 0;
10617c478bd9Sstevel@tonic-gate code = MSG_BYTE(mp, 0);
10627c478bd9Sstevel@tonic-gate if (code == PPP_ALLSTATIONS) {
10637c478bd9Sstevel@tonic-gate if (MSG_BYTE(mp, 1) == PPP_UI) {
10647c478bd9Sstevel@tonic-gate code = MSG_BYTE(mp, 2);
10657c478bd9Sstevel@tonic-gate if (code == (PPP_LCP >> 8) &&
10667c478bd9Sstevel@tonic-gate MSG_BYTE(mp, 3) == (PPP_LCP & 0xFF)) {
10677c478bd9Sstevel@tonic-gate if (LCP_USE_DFLT(mp))
10687c478bd9Sstevel@tonic-gate is_lcp = 2;
10697c478bd9Sstevel@tonic-gate else
10707c478bd9Sstevel@tonic-gate is_lcp = 1; /* Echo-Request */
10717c478bd9Sstevel@tonic-gate } else if (!(code & 1) && code > 0x3F)
10727c478bd9Sstevel@tonic-gate is_ctrl = 1;
10737c478bd9Sstevel@tonic-gate }
10747c478bd9Sstevel@tonic-gate } else if (!(code & 1) && code > 0x3F)
10757c478bd9Sstevel@tonic-gate is_ctrl = 1;
10767c478bd9Sstevel@tonic-gate
10777c478bd9Sstevel@tonic-gate /*
10787c478bd9Sstevel@tonic-gate * If it's LCP and not just an LCP Echo-Request, then we need
10797c478bd9Sstevel@tonic-gate * to drop back to default escaping rules temporarily.
10807c478bd9Sstevel@tonic-gate */
10817c478bd9Sstevel@tonic-gate if (is_lcp > 1) {
10827c478bd9Sstevel@tonic-gate /*
10837c478bd9Sstevel@tonic-gate * force escape on 0x00 through 0x1f
10847c478bd9Sstevel@tonic-gate * and, for RFC 1662 (and ISO 3309:1991), 0x80-0x9f.
10857c478bd9Sstevel@tonic-gate */
10867c478bd9Sstevel@tonic-gate loc_xaccm[0] = 0xffffffff;
10877c478bd9Sstevel@tonic-gate loc_xaccm[4] = 0xffffffff;
10887c478bd9Sstevel@tonic-gate }
10897c478bd9Sstevel@tonic-gate
10907c478bd9Sstevel@tonic-gate fcs16 = PPPINITFCS16; /* Initial FCS is 0xffff */
10917c478bd9Sstevel@tonic-gate fcs32 = PPPINITFCS32;
10927c478bd9Sstevel@tonic-gate
10937c478bd9Sstevel@tonic-gate /*
10947c478bd9Sstevel@tonic-gate * Process this block and the rest (if any) attached to this
10957c478bd9Sstevel@tonic-gate * one. Note that we quite intentionally ignore the type of
10967c478bd9Sstevel@tonic-gate * the buffer. The caller has checked that the first buffer
10977c478bd9Sstevel@tonic-gate * is M_DATA; all others must be so, and any that are not are
10987c478bd9Sstevel@tonic-gate * harmless driver errors.
10997c478bd9Sstevel@tonic-gate */
11007c478bd9Sstevel@tonic-gate curout = outmp;
11017c478bd9Sstevel@tonic-gate tpmax = outmp->b_datap->db_lim;
11027c478bd9Sstevel@tonic-gate do {
11037c478bd9Sstevel@tonic-gate dp = mp->b_rptr;
11047c478bd9Sstevel@tonic-gate while (dp < (ep = mp->b_wptr)) {
11057c478bd9Sstevel@tonic-gate /*
11067c478bd9Sstevel@tonic-gate * Calculate maximum safe run length for inner loop,
11077c478bd9Sstevel@tonic-gate * regardless of escaping.
11087c478bd9Sstevel@tonic-gate */
11097c478bd9Sstevel@tonic-gate outmp_len = (tpmax - tp) / 2;
11107c478bd9Sstevel@tonic-gate if (dp + outmp_len < ep)
11117c478bd9Sstevel@tonic-gate ep = dp + outmp_len;
11127c478bd9Sstevel@tonic-gate
11137c478bd9Sstevel@tonic-gate /*
11147c478bd9Sstevel@tonic-gate * Select out on CRC type here to make the
11157c478bd9Sstevel@tonic-gate * inner byte loop more efficient. (We could
11167c478bd9Sstevel@tonic-gate * do both CRCs at all times if we wanted, but
11177c478bd9Sstevel@tonic-gate * that ends up taking an extra 8 cycles per
11187c478bd9Sstevel@tonic-gate * byte -- 47% overhead!)
11197c478bd9Sstevel@tonic-gate */
11207c478bd9Sstevel@tonic-gate if (flags & SAF_XMITCRC32) {
11217c478bd9Sstevel@tonic-gate while (dp < ep) {
11227c478bd9Sstevel@tonic-gate chr = *dp++;
11237c478bd9Sstevel@tonic-gate fcs32 = PPPFCS32(fcs32, chr);
11247c478bd9Sstevel@tonic-gate if (IN_TX_MAP(chr, loc_xaccm)) {
11257c478bd9Sstevel@tonic-gate *tp++ = PPP_ESCAPE;
11267c478bd9Sstevel@tonic-gate chr ^= PPP_TRANS;
11277c478bd9Sstevel@tonic-gate }
11287c478bd9Sstevel@tonic-gate *tp++ = chr;
11297c478bd9Sstevel@tonic-gate }
11307c478bd9Sstevel@tonic-gate } else {
11317c478bd9Sstevel@tonic-gate while (dp < ep) {
11327c478bd9Sstevel@tonic-gate chr = *dp++;
11337c478bd9Sstevel@tonic-gate fcs16 = PPPFCS16(fcs16, chr);
11347c478bd9Sstevel@tonic-gate if (IN_TX_MAP(chr, loc_xaccm)) {
11357c478bd9Sstevel@tonic-gate *tp++ = PPP_ESCAPE;
11367c478bd9Sstevel@tonic-gate chr ^= PPP_TRANS;
11377c478bd9Sstevel@tonic-gate }
11387c478bd9Sstevel@tonic-gate *tp++ = chr;
11397c478bd9Sstevel@tonic-gate }
11407c478bd9Sstevel@tonic-gate }
11417c478bd9Sstevel@tonic-gate
11427c478bd9Sstevel@tonic-gate /*
11437c478bd9Sstevel@tonic-gate * If we limited our run length and we're now low
11447c478bd9Sstevel@tonic-gate * on output space, then allocate a new output buffer.
11457c478bd9Sstevel@tonic-gate * This should rarely happen, unless the output data
11467c478bd9Sstevel@tonic-gate * has a lot of escapes.
11477c478bd9Sstevel@tonic-gate */
11487c478bd9Sstevel@tonic-gate if (ep != mp->b_wptr && tpmax - tp < 5) {
11497c478bd9Sstevel@tonic-gate KINCR(pks_extrabufs);
11507c478bd9Sstevel@tonic-gate /* Get remaining message length */
11517c478bd9Sstevel@tonic-gate outmp_len = (mp->b_wptr - dp) +
11527c478bd9Sstevel@tonic-gate msgsize(mp->b_cont);
11537c478bd9Sstevel@tonic-gate /* Calculate maximum required space */
11547c478bd9Sstevel@tonic-gate outmp_len = (outmp_len + PPP_FCS32LEN) * 2 + 1;
11557c478bd9Sstevel@tonic-gate curout = allocb(outmp_len, BPRI_MED);
11567c478bd9Sstevel@tonic-gate if ((outmp->b_cont = curout) == NULL)
11577c478bd9Sstevel@tonic-gate goto outallocfail;
11587c478bd9Sstevel@tonic-gate outmp->b_wptr = tp;
11597c478bd9Sstevel@tonic-gate tp = curout->b_wptr;
11607c478bd9Sstevel@tonic-gate tpmax = curout->b_datap->db_lim;
11617c478bd9Sstevel@tonic-gate }
11627c478bd9Sstevel@tonic-gate }
11637c478bd9Sstevel@tonic-gate tmp = mp->b_cont;
11647c478bd9Sstevel@tonic-gate freeb(mp);
11657c478bd9Sstevel@tonic-gate mp = tmp;
11667c478bd9Sstevel@tonic-gate } while (mp != NULL);
11677c478bd9Sstevel@tonic-gate
11687c478bd9Sstevel@tonic-gate /*
11697c478bd9Sstevel@tonic-gate * Make sure we have enough remaining room to add the CRC (if
11707c478bd9Sstevel@tonic-gate * any) and a trailing flag byte.
11717c478bd9Sstevel@tonic-gate */
11727c478bd9Sstevel@tonic-gate outmp_len = PPP_FCS32LEN * 2 + 1;
11737c478bd9Sstevel@tonic-gate if (tpmax - tp < outmp_len) {
11747c478bd9Sstevel@tonic-gate KINCR(pks_extrabufs);
11757c478bd9Sstevel@tonic-gate curout = allocb(outmp_len, BPRI_MED);
11767c478bd9Sstevel@tonic-gate if ((outmp->b_cont = curout) == NULL)
11777c478bd9Sstevel@tonic-gate goto outallocfail;
11787c478bd9Sstevel@tonic-gate outmp->b_wptr = tp;
11797c478bd9Sstevel@tonic-gate tp = curout->b_wptr;
11807c478bd9Sstevel@tonic-gate tpmax = curout->b_datap->db_lim;
11817c478bd9Sstevel@tonic-gate }
11827c478bd9Sstevel@tonic-gate
11837c478bd9Sstevel@tonic-gate /*
11847c478bd9Sstevel@tonic-gate * Network layer data is the only thing that can be sent with
11857c478bd9Sstevel@tonic-gate * no CRC at all.
11867c478bd9Sstevel@tonic-gate */
11877c478bd9Sstevel@tonic-gate if ((flags & SAF_XMITCRCNONE) && !is_lcp && !is_ctrl)
11887c478bd9Sstevel@tonic-gate goto nocrc;
11897c478bd9Sstevel@tonic-gate
11907c478bd9Sstevel@tonic-gate if (!(flags & SAF_XMITCRC32))
11917c478bd9Sstevel@tonic-gate fcs32 = fcs16;
11927c478bd9Sstevel@tonic-gate
11937c478bd9Sstevel@tonic-gate /*
11947c478bd9Sstevel@tonic-gate * Append the HDLC FCS, making sure that escaping is done on any
11957c478bd9Sstevel@tonic-gate * necessary bytes. Note that the FCS bytes are in little-endian.
11967c478bd9Sstevel@tonic-gate */
11977c478bd9Sstevel@tonic-gate fcs32 = ~fcs32;
11987c478bd9Sstevel@tonic-gate chr = fcs32 & 0xff;
11997c478bd9Sstevel@tonic-gate if (IN_TX_MAP(chr, loc_xaccm)) {
12007c478bd9Sstevel@tonic-gate *tp++ = PPP_ESCAPE;
12017c478bd9Sstevel@tonic-gate chr ^= PPP_TRANS;
12027c478bd9Sstevel@tonic-gate }
12037c478bd9Sstevel@tonic-gate *tp++ = chr;
12047c478bd9Sstevel@tonic-gate
12057c478bd9Sstevel@tonic-gate chr = (fcs32 >> 8) & 0xff;
12067c478bd9Sstevel@tonic-gate if (IN_TX_MAP(chr, loc_xaccm)) {
12077c478bd9Sstevel@tonic-gate *tp++ = PPP_ESCAPE;
12087c478bd9Sstevel@tonic-gate chr ^= PPP_TRANS;
12097c478bd9Sstevel@tonic-gate }
12107c478bd9Sstevel@tonic-gate *tp++ = chr;
12117c478bd9Sstevel@tonic-gate
12127c478bd9Sstevel@tonic-gate if (flags & SAF_XMITCRC32) {
12137c478bd9Sstevel@tonic-gate chr = (fcs32 >> 16) & 0xff;
12147c478bd9Sstevel@tonic-gate if (IN_TX_MAP(chr, loc_xaccm)) {
12157c478bd9Sstevel@tonic-gate *tp++ = PPP_ESCAPE;
12167c478bd9Sstevel@tonic-gate chr ^= PPP_TRANS;
12177c478bd9Sstevel@tonic-gate }
12187c478bd9Sstevel@tonic-gate *tp++ = chr;
12197c478bd9Sstevel@tonic-gate
12207c478bd9Sstevel@tonic-gate chr = (fcs32 >> 24) & 0xff;
12217c478bd9Sstevel@tonic-gate if (IN_TX_MAP(chr, loc_xaccm)) {
12227c478bd9Sstevel@tonic-gate *tp++ = PPP_ESCAPE;
12237c478bd9Sstevel@tonic-gate chr ^= PPP_TRANS;
12247c478bd9Sstevel@tonic-gate }
12257c478bd9Sstevel@tonic-gate *tp++ = chr;
12267c478bd9Sstevel@tonic-gate }
12277c478bd9Sstevel@tonic-gate
12287c478bd9Sstevel@tonic-gate nocrc:
12297c478bd9Sstevel@tonic-gate /*
12307c478bd9Sstevel@tonic-gate * And finally append the HDLC flag, and send it away
12317c478bd9Sstevel@tonic-gate */
12327c478bd9Sstevel@tonic-gate *tp++ = PPP_FLAG;
12337c478bd9Sstevel@tonic-gate ASSERT(tp < tpmax);
12347c478bd9Sstevel@tonic-gate curout->b_wptr = tp;
12357c478bd9Sstevel@tonic-gate
12367c478bd9Sstevel@tonic-gate state->sa_stats.ppp_obytes += msgsize(outmp);
12377c478bd9Sstevel@tonic-gate state->sa_stats.ppp_opackets++;
12387c478bd9Sstevel@tonic-gate
12397c478bd9Sstevel@tonic-gate if (state->sa_flags & SAF_XMITDUMP)
12407c478bd9Sstevel@tonic-gate ppp_dump_frame(state, outmp, "sent");
12417c478bd9Sstevel@tonic-gate
12427c478bd9Sstevel@tonic-gate KINCR(pks_dataout);
12437c478bd9Sstevel@tonic-gate return (outmp);
12447c478bd9Sstevel@tonic-gate
12457c478bd9Sstevel@tonic-gate outallocfail:
12467c478bd9Sstevel@tonic-gate KINCR(pks_outallocfails);
12477c478bd9Sstevel@tonic-gate state->sa_stats.ppp_oerrors++;
12487c478bd9Sstevel@tonic-gate freemsg(outmp);
12497c478bd9Sstevel@tonic-gate freemsg(mp);
12507c478bd9Sstevel@tonic-gate (void) putnextctl1(RD(q), M_CTL, PPPCTL_OERROR);
12517c478bd9Sstevel@tonic-gate return (NULL);
12527c478bd9Sstevel@tonic-gate }
12537c478bd9Sstevel@tonic-gate
12547c478bd9Sstevel@tonic-gate /*
12557c478bd9Sstevel@tonic-gate * Handle end-of-frame excitement. This is here mostly because the Solaris
12567c478bd9Sstevel@tonic-gate * C style rules require tab for indent and prohibit excessive indenting.
12577c478bd9Sstevel@tonic-gate */
12587c478bd9Sstevel@tonic-gate static mblk_t *
receive_frame(queue_t * q,mblk_t * outmp,ushort_t fcs16,uint32_t fcs32)12597c478bd9Sstevel@tonic-gate receive_frame(queue_t *q, mblk_t *outmp, ushort_t fcs16, uint32_t fcs32)
12607c478bd9Sstevel@tonic-gate {
12617c478bd9Sstevel@tonic-gate sppp_ahdlc_t *state = (sppp_ahdlc_t *)q->q_ptr;
12627c478bd9Sstevel@tonic-gate uchar_t *cp, *ep;
12637c478bd9Sstevel@tonic-gate int is_lcp, is_ctrl, crclen;
12647c478bd9Sstevel@tonic-gate ushort_t proto;
12657c478bd9Sstevel@tonic-gate int i;
12667c478bd9Sstevel@tonic-gate
12677c478bd9Sstevel@tonic-gate cp = outmp->b_rptr;
12687c478bd9Sstevel@tonic-gate if (cp[0] == PPP_ALLSTATIONS && cp[1] == PPP_UI)
12697c478bd9Sstevel@tonic-gate cp += 2;
12707c478bd9Sstevel@tonic-gate proto = *cp++;
12717c478bd9Sstevel@tonic-gate if ((proto & 1) == 0)
12727c478bd9Sstevel@tonic-gate proto = (proto << 8) + *cp++;
12737c478bd9Sstevel@tonic-gate is_lcp = (proto == PPP_LCP);
12747c478bd9Sstevel@tonic-gate is_ctrl = (proto >= 0x4000);
12757c478bd9Sstevel@tonic-gate
12767c478bd9Sstevel@tonic-gate /*
12777c478bd9Sstevel@tonic-gate * To allow for renegotiation, LCP accepts good CRCs of either
12787c478bd9Sstevel@tonic-gate * type at any time. Other control (non-network) packets must
12797c478bd9Sstevel@tonic-gate * have either CRC-16 or CRC-32, as negotiated. Network layer
12807c478bd9Sstevel@tonic-gate * packets may additionally omit the CRC entirely, if that was
12817c478bd9Sstevel@tonic-gate * negotiated.
12827c478bd9Sstevel@tonic-gate */
12837c478bd9Sstevel@tonic-gate if ((is_lcp && (fcs16 == PPPGOODFCS16 || fcs32 == PPPGOODFCS32)) ||
12847c478bd9Sstevel@tonic-gate ((fcs16 == PPPGOODFCS16 && !(state->sa_flags & SAF_RECVCRC32)) ||
12857c478bd9Sstevel@tonic-gate (fcs32 == PPPGOODFCS32 &&
12867c478bd9Sstevel@tonic-gate (state->sa_flags & SAF_RECVCRC32))) ||
12877c478bd9Sstevel@tonic-gate (!is_ctrl && !is_lcp && (state->sa_flags & SAF_RECVCRCNONE))) {
12887c478bd9Sstevel@tonic-gate
12897c478bd9Sstevel@tonic-gate state->sa_stats.ppp_ipackets++;
12907c478bd9Sstevel@tonic-gate if (is_lcp) {
12917c478bd9Sstevel@tonic-gate crclen = (fcs16 == PPPGOODFCS16) ?
12927c478bd9Sstevel@tonic-gate PPP_FCSLEN : PPP_FCS32LEN;
12937c478bd9Sstevel@tonic-gate } else {
12947c478bd9Sstevel@tonic-gate crclen = (state->sa_flags & SAF_RECVCRC32) ?
12957c478bd9Sstevel@tonic-gate PPP_FCS32LEN : PPP_FCSLEN;
12967c478bd9Sstevel@tonic-gate if (!is_ctrl && (state->sa_flags & SAF_RECVCRCNONE))
12977c478bd9Sstevel@tonic-gate crclen = 0;
12987c478bd9Sstevel@tonic-gate }
12997c478bd9Sstevel@tonic-gate if (crclen != 0) {
13007c478bd9Sstevel@tonic-gate i = adjmsg(outmp, -crclen);
13017c478bd9Sstevel@tonic-gate ASSERT(i != 0);
13027c478bd9Sstevel@tonic-gate #if defined(lint) || defined(_lint)
13037c478bd9Sstevel@tonic-gate /* lint is happier this way in a non-DEBUG build */
13047c478bd9Sstevel@tonic-gate i = i;
13057c478bd9Sstevel@tonic-gate #endif
13067c478bd9Sstevel@tonic-gate }
13077c478bd9Sstevel@tonic-gate
13087c478bd9Sstevel@tonic-gate if (proto == PPP_MUX) {
13097c478bd9Sstevel@tonic-gate /* spppasyn_inpkt checks for PPP_MUX packets */
13107c478bd9Sstevel@tonic-gate KINCR(pks_recvmux);
13117c478bd9Sstevel@tonic-gate /* Remove headers */
13127c478bd9Sstevel@tonic-gate outmp->b_rptr = cp;
13137c478bd9Sstevel@tonic-gate return (spppasyn_inpkt(q, outmp));
13147c478bd9Sstevel@tonic-gate }
13157c478bd9Sstevel@tonic-gate
13167c478bd9Sstevel@tonic-gate /*
13177c478bd9Sstevel@tonic-gate * Sniff the received data stream. If we see an LCP
13187c478bd9Sstevel@tonic-gate * Configure-Ack, then pick out the ACCM setting, if
13197c478bd9Sstevel@tonic-gate * any, and configure now. This allows us to stay in
13207c478bd9Sstevel@tonic-gate * sync in case the peer is already out of Establish
13217c478bd9Sstevel@tonic-gate * phase.
13227c478bd9Sstevel@tonic-gate */
13237c478bd9Sstevel@tonic-gate if (is_lcp && *cp == 2) {
13247c478bd9Sstevel@tonic-gate ep = outmp->b_wptr;
13257c478bd9Sstevel@tonic-gate i = (cp[2] << 8) | cp[3];
13267c478bd9Sstevel@tonic-gate if (i > ep - cp)
13277c478bd9Sstevel@tonic-gate ep = cp; /* Discard junk */
13287c478bd9Sstevel@tonic-gate else if (i < ep - cp)
13297c478bd9Sstevel@tonic-gate ep = cp + i;
13307c478bd9Sstevel@tonic-gate cp += 4;
13317c478bd9Sstevel@tonic-gate while (cp + 2 < ep) {
13327c478bd9Sstevel@tonic-gate if ((i = cp[1]) < 2)
13337c478bd9Sstevel@tonic-gate i = 2;
13347c478bd9Sstevel@tonic-gate if (cp + i > ep)
13357c478bd9Sstevel@tonic-gate i = ep - cp;
13367c478bd9Sstevel@tonic-gate if (cp[0] == 2 && i >= 6) {
13377c478bd9Sstevel@tonic-gate state->sa_raccm = (cp[2] << 24) |
13387c478bd9Sstevel@tonic-gate (cp[3] << 16) | (cp[4] << 8) |
13397c478bd9Sstevel@tonic-gate cp[5];
13407c478bd9Sstevel@tonic-gate break;
13417c478bd9Sstevel@tonic-gate }
13427c478bd9Sstevel@tonic-gate cp += i;
13437c478bd9Sstevel@tonic-gate }
13447c478bd9Sstevel@tonic-gate }
13457c478bd9Sstevel@tonic-gate return (outmp);
13467c478bd9Sstevel@tonic-gate } else {
13477c478bd9Sstevel@tonic-gate KINCR(pks_incrcerrs);
13487c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, PPP_DRV_NAME "%d: bad fcs (len=%ld)\n",
13497c478bd9Sstevel@tonic-gate state->sa_unit, msgsize(outmp));
13507c478bd9Sstevel@tonic-gate
13517c478bd9Sstevel@tonic-gate if (state->sa_flags & SAF_RECVDUMP)
13527c478bd9Sstevel@tonic-gate ppp_dump_frame(state, outmp, "bad data");
13537c478bd9Sstevel@tonic-gate
13547c478bd9Sstevel@tonic-gate freemsg(outmp);
13557c478bd9Sstevel@tonic-gate
13567c478bd9Sstevel@tonic-gate state->sa_stats.ppp_ierrors++;
13577c478bd9Sstevel@tonic-gate
13587c478bd9Sstevel@tonic-gate (void) putnextctl1(q, M_CTL, PPPCTL_IERROR);
13597c478bd9Sstevel@tonic-gate return (NULL);
13607c478bd9Sstevel@tonic-gate }
13617c478bd9Sstevel@tonic-gate }
13627c478bd9Sstevel@tonic-gate
13637c478bd9Sstevel@tonic-gate /*
13647c478bd9Sstevel@tonic-gate * ahdlc_decode()
13657c478bd9Sstevel@tonic-gate *
13667c478bd9Sstevel@tonic-gate * Process received characters.
13677c478bd9Sstevel@tonic-gate *
13687c478bd9Sstevel@tonic-gate * This is handled as exclusive inner so that we don't get confused
13697c478bd9Sstevel@tonic-gate * about the state. Returns a list of packets linked by b_next.
13707c478bd9Sstevel@tonic-gate */
13717c478bd9Sstevel@tonic-gate static mblk_t *
ahdlc_decode(queue_t * q,mblk_t * mp)13727c478bd9Sstevel@tonic-gate ahdlc_decode(queue_t *q, mblk_t *mp)
13737c478bd9Sstevel@tonic-gate {
13747c478bd9Sstevel@tonic-gate sppp_ahdlc_t *state;
13757c478bd9Sstevel@tonic-gate mblk_t *retmp; /* list of packets to return */
13767c478bd9Sstevel@tonic-gate mblk_t *outmp; /* buffer for decoded data */
13777c478bd9Sstevel@tonic-gate mblk_t *mpnext; /* temporary ptr for unlinking */
13787c478bd9Sstevel@tonic-gate uchar_t *dp; /* pointer to input data */
13797c478bd9Sstevel@tonic-gate uchar_t *dpend; /* end of input data */
13807c478bd9Sstevel@tonic-gate uchar_t *tp; /* pointer to decoded output data */
13817c478bd9Sstevel@tonic-gate uchar_t *tpmax; /* output buffer limit */
13827c478bd9Sstevel@tonic-gate int flagtmp; /* temporary cache of flags */
13837c478bd9Sstevel@tonic-gate #if defined(lint) || defined(_lint)
13847c478bd9Sstevel@tonic-gate uchar_t chr; /* lint likes this */
13857c478bd9Sstevel@tonic-gate #else
13867c478bd9Sstevel@tonic-gate int chr; /* not uchar_t; more efficient this way */
13877c478bd9Sstevel@tonic-gate /* with WorkShop compiler */
13887c478bd9Sstevel@tonic-gate #endif
13897c478bd9Sstevel@tonic-gate ushort_t fcs16; /* running CRC-16 */
13907c478bd9Sstevel@tonic-gate uint32_t fcs32; /* running CRC-32 */
13917c478bd9Sstevel@tonic-gate #ifdef HANDLE_ZERO_LENGTH
13927c478bd9Sstevel@tonic-gate size_t nprocessed;
13937c478bd9Sstevel@tonic-gate #endif
13947c478bd9Sstevel@tonic-gate
13957c478bd9Sstevel@tonic-gate state = (sppp_ahdlc_t *)q->q_ptr;
13967c478bd9Sstevel@tonic-gate
13977c478bd9Sstevel@tonic-gate KINCR(pks_datain);
13987c478bd9Sstevel@tonic-gate
13997c478bd9Sstevel@tonic-gate state->sa_stats.ppp_ibytes += msgsize(mp);
14007c478bd9Sstevel@tonic-gate
14017c478bd9Sstevel@tonic-gate if (state->sa_flags & SAF_RECVDUMP)
14027c478bd9Sstevel@tonic-gate ppp_dump_frame(state, mp, "rcvd");
14037c478bd9Sstevel@tonic-gate
14047c478bd9Sstevel@tonic-gate flagtmp = state->sa_flags;
14057c478bd9Sstevel@tonic-gate fcs16 = state->sa_infcs16;
14067c478bd9Sstevel@tonic-gate fcs32 = state->sa_infcs32;
14077c478bd9Sstevel@tonic-gate outmp = state->sa_rx_buf;
14087c478bd9Sstevel@tonic-gate if (outmp == NULL) {
14097c478bd9Sstevel@tonic-gate tp = tpmax = NULL;
14107c478bd9Sstevel@tonic-gate } else {
14117c478bd9Sstevel@tonic-gate tp = outmp->b_wptr;
14127c478bd9Sstevel@tonic-gate tpmax = outmp->b_datap->db_lim;
14137c478bd9Sstevel@tonic-gate }
14147c478bd9Sstevel@tonic-gate #ifdef HANDLE_ZERO_LENGTH
14157c478bd9Sstevel@tonic-gate nprocessed = 0;
14167c478bd9Sstevel@tonic-gate #endif
14177c478bd9Sstevel@tonic-gate
14187c478bd9Sstevel@tonic-gate /*
14197c478bd9Sstevel@tonic-gate * Main input processing loop. Loop over received buffers and
14207c478bd9Sstevel@tonic-gate * each byte in each buffer. Note that we quite intentionally
14217c478bd9Sstevel@tonic-gate * ignore the type of the buffer. The caller has checked that
14227c478bd9Sstevel@tonic-gate * the first buffer is M_DATA; all others must be so, and any
14237c478bd9Sstevel@tonic-gate * that are not are harmless driver errors.
14247c478bd9Sstevel@tonic-gate */
14257c478bd9Sstevel@tonic-gate retmp = NULL;
14267c478bd9Sstevel@tonic-gate while (mp != NULL) {
14277c478bd9Sstevel@tonic-gate
14287c478bd9Sstevel@tonic-gate /* Innermost loop -- examine bytes in buffer. */
14297c478bd9Sstevel@tonic-gate dpend = mp->b_wptr;
14307c478bd9Sstevel@tonic-gate dp = mp->b_rptr;
14317c478bd9Sstevel@tonic-gate #ifdef HANDLE_ZERO_LENGTH
14327c478bd9Sstevel@tonic-gate nprocessed += dpend - dp;
14337c478bd9Sstevel@tonic-gate #endif
14347c478bd9Sstevel@tonic-gate for (; dp < dpend; dp++) {
14357c478bd9Sstevel@tonic-gate chr = *dp;
14367c478bd9Sstevel@tonic-gate
14377c478bd9Sstevel@tonic-gate /*
14387c478bd9Sstevel@tonic-gate * This should detect the lack of an 8-bit
14397c478bd9Sstevel@tonic-gate * communication channel, which is necessary
14407c478bd9Sstevel@tonic-gate * for PPP to work.
14417c478bd9Sstevel@tonic-gate */
14427c478bd9Sstevel@tonic-gate flagtmp |= charflags[chr];
14437c478bd9Sstevel@tonic-gate
14447c478bd9Sstevel@tonic-gate /*
14457c478bd9Sstevel@tonic-gate * So we have a HDLC flag ...
14467c478bd9Sstevel@tonic-gate */
14477c478bd9Sstevel@tonic-gate if (chr == PPP_FLAG) {
14487c478bd9Sstevel@tonic-gate
14497c478bd9Sstevel@tonic-gate /*
14507c478bd9Sstevel@tonic-gate * If there's no received buffer, then
14517c478bd9Sstevel@tonic-gate * just ignore this frame marker.
14527c478bd9Sstevel@tonic-gate */
14537c478bd9Sstevel@tonic-gate if ((flagtmp & SAF_IFLUSH) || outmp == NULL) {
14547c478bd9Sstevel@tonic-gate flagtmp &= ~SAF_IFLUSH & ~SAF_ESCAPED;
14557c478bd9Sstevel@tonic-gate continue;
14567c478bd9Sstevel@tonic-gate }
14577c478bd9Sstevel@tonic-gate
14587c478bd9Sstevel@tonic-gate /*
14597c478bd9Sstevel@tonic-gate * Per RFC 1662 -- silently discard
14607c478bd9Sstevel@tonic-gate * runt frames (fewer than 4 octets
14617c478bd9Sstevel@tonic-gate * with 16 bit CRC) and frames that
14627c478bd9Sstevel@tonic-gate * end in 7D 7E (abort sequence).
14637c478bd9Sstevel@tonic-gate * These are not counted as errors.
14647c478bd9Sstevel@tonic-gate *
14657c478bd9Sstevel@tonic-gate * (We could just reset the pointers
14667c478bd9Sstevel@tonic-gate * and reuse the buffer, but this is a
14677c478bd9Sstevel@tonic-gate * rarely used error path and not
14687c478bd9Sstevel@tonic-gate * worth the optimization.)
14697c478bd9Sstevel@tonic-gate */
14707c478bd9Sstevel@tonic-gate if ((flagtmp & SAF_ESCAPED) ||
14717c478bd9Sstevel@tonic-gate tp - outmp->b_rptr < 2 + PPP_FCSLEN) {
14727c478bd9Sstevel@tonic-gate if (flagtmp & SAF_ESCAPED)
14737c478bd9Sstevel@tonic-gate KINCR(pks_inaborts);
14747c478bd9Sstevel@tonic-gate else
14757c478bd9Sstevel@tonic-gate KINCR(pks_inrunts);
14767c478bd9Sstevel@tonic-gate if (state->sa_flags & SAF_RECVDUMP) {
14777c478bd9Sstevel@tonic-gate outmp->b_wptr = tp;
14787c478bd9Sstevel@tonic-gate ppp_dump_frame(state, outmp,
14797c478bd9Sstevel@tonic-gate "runt");
14807c478bd9Sstevel@tonic-gate }
14817c478bd9Sstevel@tonic-gate freemsg(outmp);
14827c478bd9Sstevel@tonic-gate flagtmp &= ~SAF_ESCAPED;
14837c478bd9Sstevel@tonic-gate } else {
14847c478bd9Sstevel@tonic-gate /* Handle the received frame */
14857c478bd9Sstevel@tonic-gate outmp->b_wptr = tp;
14867c478bd9Sstevel@tonic-gate outmp = receive_frame(q, outmp, fcs16,
14877c478bd9Sstevel@tonic-gate fcs32);
14887c478bd9Sstevel@tonic-gate retmp = sppp_mappend(retmp, outmp);
14897c478bd9Sstevel@tonic-gate }
14907c478bd9Sstevel@tonic-gate
14917c478bd9Sstevel@tonic-gate outmp = NULL;
14927c478bd9Sstevel@tonic-gate tp = tpmax = NULL;
14937c478bd9Sstevel@tonic-gate
14947c478bd9Sstevel@tonic-gate continue;
14957c478bd9Sstevel@tonic-gate }
14967c478bd9Sstevel@tonic-gate
14977c478bd9Sstevel@tonic-gate /* If we're waiting for a new frame, then drop data. */
14987c478bd9Sstevel@tonic-gate if (flagtmp & SAF_IFLUSH) {
14997c478bd9Sstevel@tonic-gate continue;
15007c478bd9Sstevel@tonic-gate }
15017c478bd9Sstevel@tonic-gate
15027c478bd9Sstevel@tonic-gate /*
15037c478bd9Sstevel@tonic-gate * Start of new frame. Allocate a receive
15047c478bd9Sstevel@tonic-gate * buffer large enough to store a frame (after
15057c478bd9Sstevel@tonic-gate * un-escaping) of at least 1500 octets plus
15067c478bd9Sstevel@tonic-gate * the CRC. If MRU is negotiated to be more
15077c478bd9Sstevel@tonic-gate * than the default, then allocate that much.
15087c478bd9Sstevel@tonic-gate * In addition, we add an extra 32-bytes for a
15097c478bd9Sstevel@tonic-gate * fudge factor, in case the peer doesn't do
15107c478bd9Sstevel@tonic-gate * arithmetic very well.
15117c478bd9Sstevel@tonic-gate */
15127c478bd9Sstevel@tonic-gate if (outmp == NULL) {
15137c478bd9Sstevel@tonic-gate int maxlen;
15147c478bd9Sstevel@tonic-gate
15157c478bd9Sstevel@tonic-gate if ((maxlen = state->sa_mru) < PPP_MRU)
15167c478bd9Sstevel@tonic-gate maxlen = PPP_MRU;
15177c478bd9Sstevel@tonic-gate maxlen += PPP_FCS32LEN + 32;
15187c478bd9Sstevel@tonic-gate outmp = allocb(maxlen, BPRI_MED);
15197c478bd9Sstevel@tonic-gate
15207c478bd9Sstevel@tonic-gate /*
15217c478bd9Sstevel@tonic-gate * If allocation fails, try again on
15227c478bd9Sstevel@tonic-gate * the next frame. (Go into discard
15237c478bd9Sstevel@tonic-gate * mode.)
15247c478bd9Sstevel@tonic-gate */
15257c478bd9Sstevel@tonic-gate if (outmp == NULL) {
15267c478bd9Sstevel@tonic-gate KINCR(pks_inallocfails);
15277c478bd9Sstevel@tonic-gate flagtmp |= SAF_IFLUSH;
15287c478bd9Sstevel@tonic-gate continue;
15297c478bd9Sstevel@tonic-gate }
15307c478bd9Sstevel@tonic-gate
15317c478bd9Sstevel@tonic-gate tp = outmp->b_wptr;
15327c478bd9Sstevel@tonic-gate tpmax = outmp->b_datap->db_lim;
15337c478bd9Sstevel@tonic-gate
15347c478bd9Sstevel@tonic-gate /* Neither flag can possibly be set here. */
15357c478bd9Sstevel@tonic-gate flagtmp &= ~(SAF_IFLUSH | SAF_ESCAPED);
15367c478bd9Sstevel@tonic-gate fcs16 = PPPINITFCS16;
15377c478bd9Sstevel@tonic-gate fcs32 = PPPINITFCS32;
15387c478bd9Sstevel@tonic-gate }
15397c478bd9Sstevel@tonic-gate
15407c478bd9Sstevel@tonic-gate /*
15417c478bd9Sstevel@tonic-gate * If the peer sends us a character that's in
15427c478bd9Sstevel@tonic-gate * our receive character map, then that's
15437c478bd9Sstevel@tonic-gate * junk. Discard it without changing state.
15447c478bd9Sstevel@tonic-gate * If he previously sent us an escape
15457c478bd9Sstevel@tonic-gate * character, then toggle this one and
15467c478bd9Sstevel@tonic-gate * continue. Otherwise, if he's now sending
15477c478bd9Sstevel@tonic-gate * escape, set the flag for next time.
15487c478bd9Sstevel@tonic-gate */
15497c478bd9Sstevel@tonic-gate if (IN_RX_MAP(chr, state->sa_raccm)) {
15507c478bd9Sstevel@tonic-gate KINCR(pks_inbadchars);
15517c478bd9Sstevel@tonic-gate KOR(pks_inbadcharmask, 1 << chr);
15527c478bd9Sstevel@tonic-gate continue;
15537c478bd9Sstevel@tonic-gate }
15547c478bd9Sstevel@tonic-gate if (flagtmp & SAF_ESCAPED) {
15557c478bd9Sstevel@tonic-gate chr ^= PPP_TRANS;
15567c478bd9Sstevel@tonic-gate flagtmp &= ~SAF_ESCAPED;
15577c478bd9Sstevel@tonic-gate } else if (chr == PPP_ESCAPE) {
15587c478bd9Sstevel@tonic-gate flagtmp |= SAF_ESCAPED;
15597c478bd9Sstevel@tonic-gate continue;
15607c478bd9Sstevel@tonic-gate }
15617c478bd9Sstevel@tonic-gate
15627c478bd9Sstevel@tonic-gate /*
15637c478bd9Sstevel@tonic-gate * Unless the peer is confused about the
15647c478bd9Sstevel@tonic-gate * negotiated MRU, we should never get a frame
15657c478bd9Sstevel@tonic-gate * that is too long. If it happens, toss it
15667c478bd9Sstevel@tonic-gate * away and begin discarding data until we see
15677c478bd9Sstevel@tonic-gate * the end of the frame.
15687c478bd9Sstevel@tonic-gate */
15697c478bd9Sstevel@tonic-gate if (tp < tpmax) {
15707c478bd9Sstevel@tonic-gate fcs16 = PPPFCS16(fcs16, chr);
15717c478bd9Sstevel@tonic-gate fcs32 = PPPFCS32(fcs32, chr);
15727c478bd9Sstevel@tonic-gate *tp++ = chr;
15737c478bd9Sstevel@tonic-gate } else {
15747c478bd9Sstevel@tonic-gate KINCR(pks_intoolongs);
15757c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, PPP_DRV_NAME
15767c478bd9Sstevel@tonic-gate "%d: frame too long (%d bytes)\n",
15777c478bd9Sstevel@tonic-gate state->sa_unit,
15787c478bd9Sstevel@tonic-gate (int)(tpmax - outmp->b_rptr));
15797c478bd9Sstevel@tonic-gate
15807c478bd9Sstevel@tonic-gate freemsg(outmp);
15817c478bd9Sstevel@tonic-gate outmp = NULL;
15827c478bd9Sstevel@tonic-gate tp = tpmax = NULL;
15837c478bd9Sstevel@tonic-gate flagtmp |= SAF_IFLUSH;
15847c478bd9Sstevel@tonic-gate }
15857c478bd9Sstevel@tonic-gate }
15867c478bd9Sstevel@tonic-gate
15877c478bd9Sstevel@tonic-gate /*
15887c478bd9Sstevel@tonic-gate * Free the buffer we just processed and move on to
15897c478bd9Sstevel@tonic-gate * the next one.
15907c478bd9Sstevel@tonic-gate */
15917c478bd9Sstevel@tonic-gate mpnext = mp->b_cont;
15927c478bd9Sstevel@tonic-gate freeb(mp);
15937c478bd9Sstevel@tonic-gate mp = mpnext;
15947c478bd9Sstevel@tonic-gate }
15957c478bd9Sstevel@tonic-gate state->sa_flags = flagtmp;
15967c478bd9Sstevel@tonic-gate if ((state->sa_rx_buf = outmp) != NULL)
15977c478bd9Sstevel@tonic-gate outmp->b_wptr = tp;
15987c478bd9Sstevel@tonic-gate state->sa_infcs16 = fcs16;
15997c478bd9Sstevel@tonic-gate state->sa_infcs32 = fcs32;
16007c478bd9Sstevel@tonic-gate
16017c478bd9Sstevel@tonic-gate #ifdef HANDLE_ZERO_LENGTH
16027c478bd9Sstevel@tonic-gate if (nprocessed <= 0) {
16037c478bd9Sstevel@tonic-gate outmp = allocb(0, BPRI_MED);
16047c478bd9Sstevel@tonic-gate if (outmp != NULL) {
16057c478bd9Sstevel@tonic-gate outmp->b_datap->db_type = M_HANGUP;
16067c478bd9Sstevel@tonic-gate retmp = sppp_mappend(retmp, outmp);
16077c478bd9Sstevel@tonic-gate }
16087c478bd9Sstevel@tonic-gate }
16097c478bd9Sstevel@tonic-gate #endif
16107c478bd9Sstevel@tonic-gate return (retmp);
16117c478bd9Sstevel@tonic-gate }
16127c478bd9Sstevel@tonic-gate
16137c478bd9Sstevel@tonic-gate /*
16147c478bd9Sstevel@tonic-gate * Nifty packet dumper; copied from AIX 4.1 port. This routine dumps
16157c478bd9Sstevel@tonic-gate * the raw received and transmitted data through syslog. This allows
16167c478bd9Sstevel@tonic-gate * debug of communications problems without resorting to a line
16177c478bd9Sstevel@tonic-gate * analyzer.
16187c478bd9Sstevel@tonic-gate *
16197c478bd9Sstevel@tonic-gate * The expression "3*BYTES_PER_LINE" used frequently here represents
16207c478bd9Sstevel@tonic-gate * the size of each hex value printed -- two hex digits and a space.
16217c478bd9Sstevel@tonic-gate */
16227c478bd9Sstevel@tonic-gate #define BYTES_PER_LINE 8
16237c478bd9Sstevel@tonic-gate static void
ppp_dump_frame(sppp_ahdlc_t * state,mblk_t * mptr,const char * msg)16247c478bd9Sstevel@tonic-gate ppp_dump_frame(sppp_ahdlc_t *state, mblk_t *mptr, const char *msg)
16257c478bd9Sstevel@tonic-gate {
16267c478bd9Sstevel@tonic-gate /*
16277c478bd9Sstevel@tonic-gate * Buffer is big enough for hex digits, two spaces, ASCII output,
16287c478bd9Sstevel@tonic-gate * and one NUL byte.
16297c478bd9Sstevel@tonic-gate */
16307c478bd9Sstevel@tonic-gate char buf[3 * BYTES_PER_LINE + 2 + BYTES_PER_LINE + 1];
16317c478bd9Sstevel@tonic-gate uchar_t *rptr, *eptr;
16327c478bd9Sstevel@tonic-gate int i, chr;
16337c478bd9Sstevel@tonic-gate char *bp;
16347c478bd9Sstevel@tonic-gate static const char digits[] = "0123456789abcdef";
16357c478bd9Sstevel@tonic-gate
16367c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "!ppp_async%d: %s %ld bytes\n", state->sa_unit,
16377c478bd9Sstevel@tonic-gate msg, msgsize(mptr));
16387c478bd9Sstevel@tonic-gate i = 0;
16397c478bd9Sstevel@tonic-gate bp = buf;
16407c478bd9Sstevel@tonic-gate /* Add filler spaces between hex output and ASCII */
16417c478bd9Sstevel@tonic-gate buf[3 * BYTES_PER_LINE] = ' ';
16427c478bd9Sstevel@tonic-gate buf[3 * BYTES_PER_LINE + 1] = ' ';
16437c478bd9Sstevel@tonic-gate /* Add NUL byte at end */
16447c478bd9Sstevel@tonic-gate buf[sizeof (buf) - 1] = '\0';
16457c478bd9Sstevel@tonic-gate while (mptr != NULL) {
16467c478bd9Sstevel@tonic-gate rptr = mptr->b_rptr; /* get pointer to beginning */
16477c478bd9Sstevel@tonic-gate eptr = mptr->b_wptr;
16487c478bd9Sstevel@tonic-gate while (rptr < eptr) {
16497c478bd9Sstevel@tonic-gate chr = *rptr++;
16507c478bd9Sstevel@tonic-gate /* convert byte to ascii hex */
16517c478bd9Sstevel@tonic-gate *bp++ = digits[chr >> 4];
16527c478bd9Sstevel@tonic-gate *bp++ = digits[chr & 0xf];
16537c478bd9Sstevel@tonic-gate *bp++ = ' ';
16547c478bd9Sstevel@tonic-gate /* Insert ASCII past hex output and filler */
16557c478bd9Sstevel@tonic-gate buf[3 * BYTES_PER_LINE + 2 + i] =
16567c478bd9Sstevel@tonic-gate (chr >= 0x20 && chr <= 0x7E) ? (char)chr : '.';
16577c478bd9Sstevel@tonic-gate i++;
16587c478bd9Sstevel@tonic-gate if (i >= BYTES_PER_LINE) {
16597c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "!ppp%d: %s\n", state->sa_unit,
16607c478bd9Sstevel@tonic-gate buf);
16617c478bd9Sstevel@tonic-gate bp = buf;
16627c478bd9Sstevel@tonic-gate i = 0;
16637c478bd9Sstevel@tonic-gate }
16647c478bd9Sstevel@tonic-gate }
16657c478bd9Sstevel@tonic-gate mptr = mptr->b_cont;
16667c478bd9Sstevel@tonic-gate }
16677c478bd9Sstevel@tonic-gate if (bp > buf) {
16687c478bd9Sstevel@tonic-gate /* fill over unused hex display positions */
16697c478bd9Sstevel@tonic-gate while (bp < buf + 3 * BYTES_PER_LINE)
16707c478bd9Sstevel@tonic-gate *bp++ = ' ';
16717c478bd9Sstevel@tonic-gate /* terminate ASCII string at right position */
16727c478bd9Sstevel@tonic-gate buf[3 * BYTES_PER_LINE + 2 + i] = '\0';
16737c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "!ppp%d: %s\n", state->sa_unit, buf);
16747c478bd9Sstevel@tonic-gate }
16757c478bd9Sstevel@tonic-gate }
16767c478bd9Sstevel@tonic-gate
16777c478bd9Sstevel@tonic-gate static mblk_t *
spppasyn_muxencode(queue_t * q,mblk_t * mp)16787c478bd9Sstevel@tonic-gate spppasyn_muxencode(queue_t *q, mblk_t *mp)
16797c478bd9Sstevel@tonic-gate {
16807c478bd9Sstevel@tonic-gate sppp_ahdlc_t *state = (sppp_ahdlc_t *)q->q_ptr;
16817c478bd9Sstevel@tonic-gate uint32_t len;
16827c478bd9Sstevel@tonic-gate uint32_t nlen;
16837c478bd9Sstevel@tonic-gate ushort_t protolen;
16847c478bd9Sstevel@tonic-gate uint32_t hdrlen;
16857c478bd9Sstevel@tonic-gate ushort_t proto;
16867c478bd9Sstevel@tonic-gate mblk_t *new_frame;
16877c478bd9Sstevel@tonic-gate mblk_t *tmp;
16887c478bd9Sstevel@tonic-gate mblk_t *send_frame;
16897c478bd9Sstevel@tonic-gate ushort_t i;
16907c478bd9Sstevel@tonic-gate
16917c478bd9Sstevel@tonic-gate len = msgdsize(mp);
16927c478bd9Sstevel@tonic-gate i = 0;
16937c478bd9Sstevel@tonic-gate protolen = 1;
16947c478bd9Sstevel@tonic-gate proto = MSG_BYTE(mp, i);
16957c478bd9Sstevel@tonic-gate
16967c478bd9Sstevel@tonic-gate if (proto == PPP_ALLSTATIONS) {
16977c478bd9Sstevel@tonic-gate len -= 2;
16987c478bd9Sstevel@tonic-gate i += 2;
16997c478bd9Sstevel@tonic-gate proto = MSG_BYTE(mp, i);
17007c478bd9Sstevel@tonic-gate }
17017c478bd9Sstevel@tonic-gate
17027c478bd9Sstevel@tonic-gate ++i;
17037c478bd9Sstevel@tonic-gate if ((proto & 1) == 0) {
17047c478bd9Sstevel@tonic-gate proto = (proto << 8) + MSG_BYTE(mp, i);
17057c478bd9Sstevel@tonic-gate protolen++;
17067c478bd9Sstevel@tonic-gate }
17077c478bd9Sstevel@tonic-gate
17087c478bd9Sstevel@tonic-gate hdrlen = i - 1;
17097c478bd9Sstevel@tonic-gate
17107c478bd9Sstevel@tonic-gate send_frame = NULL;
17117c478bd9Sstevel@tonic-gate if (len > PPP_MAX_MUX_LEN || (proto & 0x8000)) {
17127c478bd9Sstevel@tonic-gate
17137c478bd9Sstevel@tonic-gate /* send the queued frames */
17147c478bd9Sstevel@tonic-gate if (state->sa_mqhead != NULL) {
17157c478bd9Sstevel@tonic-gate /* increment counter if it is MUX pkt */
17167c478bd9Sstevel@tonic-gate if (state->sa_mqtail != NULL)
17177c478bd9Sstevel@tonic-gate KINCR(pks_sentmux);
17187c478bd9Sstevel@tonic-gate send_frame = ahdlc_encode(q, state->sa_mqhead);
17197c478bd9Sstevel@tonic-gate }
17207c478bd9Sstevel@tonic-gate
17217c478bd9Sstevel@tonic-gate /* send the current frame */
17227c478bd9Sstevel@tonic-gate mp = ahdlc_encode(q, mp);
17237c478bd9Sstevel@tonic-gate send_frame = sppp_mcat(send_frame, mp);
17247c478bd9Sstevel@tonic-gate
17257c478bd9Sstevel@tonic-gate /* reset the state values over here */
17267c478bd9Sstevel@tonic-gate RESET_MUX_VALUES(state);
17277c478bd9Sstevel@tonic-gate return (send_frame);
17287c478bd9Sstevel@tonic-gate }
17297c478bd9Sstevel@tonic-gate
17307c478bd9Sstevel@tonic-gate /* len + 1 , since we add the mux overhead */
17317c478bd9Sstevel@tonic-gate nlen = len + 1;
17327c478bd9Sstevel@tonic-gate /* subtract the protocol length if protocol matches */
17337c478bd9Sstevel@tonic-gate if (state->sa_proto == proto)
17347c478bd9Sstevel@tonic-gate nlen -= protolen;
17357c478bd9Sstevel@tonic-gate
17367c478bd9Sstevel@tonic-gate send_frame = NULL;
17377c478bd9Sstevel@tonic-gate if ((state->sa_mqlen + nlen) >= state->sa_mru) {
17387c478bd9Sstevel@tonic-gate
17397c478bd9Sstevel@tonic-gate /* send the existing queued frames */
17407c478bd9Sstevel@tonic-gate if (state->sa_mqhead != NULL) {
17417c478bd9Sstevel@tonic-gate /* increment counter if it is MUX pkt */
17427c478bd9Sstevel@tonic-gate if (state->sa_mqtail != NULL)
17437c478bd9Sstevel@tonic-gate KINCR(pks_sentmux);
17447c478bd9Sstevel@tonic-gate send_frame = ahdlc_encode(q, state->sa_mqhead);
17457c478bd9Sstevel@tonic-gate }
17467c478bd9Sstevel@tonic-gate
17477c478bd9Sstevel@tonic-gate /* reset state values */
17487c478bd9Sstevel@tonic-gate RESET_MUX_VALUES(state);
17497c478bd9Sstevel@tonic-gate }
17507c478bd9Sstevel@tonic-gate
17517c478bd9Sstevel@tonic-gate /* add the current frame to the queue */
17527c478bd9Sstevel@tonic-gate if (state->sa_mqhead != NULL) {
17537c478bd9Sstevel@tonic-gate
17547c478bd9Sstevel@tonic-gate if (state->sa_mqtail == NULL) {
17557c478bd9Sstevel@tonic-gate
17567c478bd9Sstevel@tonic-gate /*
17577c478bd9Sstevel@tonic-gate * this is the first mblk in the queue create
17587c478bd9Sstevel@tonic-gate * a new frame to hold the PPP MUX header
17597c478bd9Sstevel@tonic-gate */
17607c478bd9Sstevel@tonic-gate if ((new_frame = allocb(PPP_HDRLEN+1,
17617c478bd9Sstevel@tonic-gate BPRI_MED)) == NULL) {
17627c478bd9Sstevel@tonic-gate return (send_frame);
17637c478bd9Sstevel@tonic-gate }
17647c478bd9Sstevel@tonic-gate
17657c478bd9Sstevel@tonic-gate if (!IS_COMP_AC(state)) {
17667c478bd9Sstevel@tonic-gate /* add the header */
17677c478bd9Sstevel@tonic-gate *new_frame->b_wptr++ = PPP_ALLSTATIONS;
17687c478bd9Sstevel@tonic-gate *new_frame->b_wptr++ = PPP_UI;
17697c478bd9Sstevel@tonic-gate }
17707c478bd9Sstevel@tonic-gate
17717c478bd9Sstevel@tonic-gate /* do protocol compression */
17727c478bd9Sstevel@tonic-gate if (IS_COMP_PROT(state)) {
17737c478bd9Sstevel@tonic-gate *new_frame->b_wptr++ = PPP_MUX;
17747c478bd9Sstevel@tonic-gate } else {
17757c478bd9Sstevel@tonic-gate *new_frame->b_wptr++ = 0;
17767c478bd9Sstevel@tonic-gate *new_frame->b_wptr++ = PPP_MUX;
17777c478bd9Sstevel@tonic-gate }
17787c478bd9Sstevel@tonic-gate
17797c478bd9Sstevel@tonic-gate *new_frame->b_wptr++ = PFF |
17807c478bd9Sstevel@tonic-gate (state->sa_mqlen - protolen - 1);
17817c478bd9Sstevel@tonic-gate
17827c478bd9Sstevel@tonic-gate if (DB_REF(mp) > 1) {
17837c478bd9Sstevel@tonic-gate tmp = copymsg(state->sa_mqhead);
17847c478bd9Sstevel@tonic-gate freemsg(state->sa_mqhead);
17857c478bd9Sstevel@tonic-gate if ((state->sa_mqhead = tmp) == NULL) {
17867c478bd9Sstevel@tonic-gate return (send_frame);
17877c478bd9Sstevel@tonic-gate }
17887c478bd9Sstevel@tonic-gate }
17897c478bd9Sstevel@tonic-gate
17907c478bd9Sstevel@tonic-gate if (state->sa_mqhead->b_rptr[0] == PPP_ALLSTATIONS)
17917c478bd9Sstevel@tonic-gate state->sa_mqhead->b_rptr += 2;
17927c478bd9Sstevel@tonic-gate
17937c478bd9Sstevel@tonic-gate linkb(new_frame, state->sa_mqhead);
17947c478bd9Sstevel@tonic-gate state->sa_mqtail = state->sa_mqhead;
17957c478bd9Sstevel@tonic-gate /* point mqtail to the last mblk_t */
17967c478bd9Sstevel@tonic-gate while (state->sa_mqtail->b_cont != NULL)
17977c478bd9Sstevel@tonic-gate state->sa_mqtail = state->sa_mqtail->b_cont;
17987c478bd9Sstevel@tonic-gate
17997c478bd9Sstevel@tonic-gate /* change state->sa_mqhead */
18007c478bd9Sstevel@tonic-gate state->sa_mqhead = new_frame;
18017c478bd9Sstevel@tonic-gate
18027c478bd9Sstevel@tonic-gate }
18037c478bd9Sstevel@tonic-gate
18047c478bd9Sstevel@tonic-gate if (state->sa_proto == proto) {
18057c478bd9Sstevel@tonic-gate
18067c478bd9Sstevel@tonic-gate /* Check if the mblk_t is being referenced */
18077c478bd9Sstevel@tonic-gate if (DB_REF(mp) > 1) {
18087c478bd9Sstevel@tonic-gate tmp = copymsg(mp);
18097c478bd9Sstevel@tonic-gate freemsg(mp);
18107c478bd9Sstevel@tonic-gate if ((mp = tmp) == NULL) {
18117c478bd9Sstevel@tonic-gate return (send_frame);
18127c478bd9Sstevel@tonic-gate }
18137c478bd9Sstevel@tonic-gate }
18147c478bd9Sstevel@tonic-gate
18157c478bd9Sstevel@tonic-gate /*
18167c478bd9Sstevel@tonic-gate * match,can remove the protocol field
18177c478bd9Sstevel@tonic-gate * and write data there
18187c478bd9Sstevel@tonic-gate */
18197c478bd9Sstevel@tonic-gate mp->b_rptr += hdrlen;
18207c478bd9Sstevel@tonic-gate /*
18217c478bd9Sstevel@tonic-gate * protolen - 1 ,because the the byte with
18227c478bd9Sstevel@tonic-gate * the PFF bit and the length field have
18237c478bd9Sstevel@tonic-gate * to added
18247c478bd9Sstevel@tonic-gate */
18257c478bd9Sstevel@tonic-gate mp->b_rptr += (protolen - 1);
18267c478bd9Sstevel@tonic-gate *mp->b_rptr = (len - protolen) & 0xff;
18277c478bd9Sstevel@tonic-gate
18287c478bd9Sstevel@tonic-gate } else {
18297c478bd9Sstevel@tonic-gate /*
18307c478bd9Sstevel@tonic-gate * no match, there are three options
18317c478bd9Sstevel@tonic-gate * 1. write in mp
18327c478bd9Sstevel@tonic-gate * 2. write in mqtail
18337c478bd9Sstevel@tonic-gate * 3. alloc a new blk for just one byte
18347c478bd9Sstevel@tonic-gate */
18357c478bd9Sstevel@tonic-gate /* Check if the mblk_t is being referenced */
18367c478bd9Sstevel@tonic-gate if (DB_REF(mp) > 1) {
18377c478bd9Sstevel@tonic-gate tmp = copymsg(mp);
18387c478bd9Sstevel@tonic-gate freemsg(mp);
18397c478bd9Sstevel@tonic-gate if ((mp = tmp) == NULL) {
18407c478bd9Sstevel@tonic-gate return (send_frame);
18417c478bd9Sstevel@tonic-gate }
18427c478bd9Sstevel@tonic-gate }
18437c478bd9Sstevel@tonic-gate
18447c478bd9Sstevel@tonic-gate if (hdrlen != 0) {
18457c478bd9Sstevel@tonic-gate
18467c478bd9Sstevel@tonic-gate mp->b_rptr += (hdrlen-1);
18477c478bd9Sstevel@tonic-gate *mp->b_rptr = PFF | (len);
18487c478bd9Sstevel@tonic-gate
18497c478bd9Sstevel@tonic-gate } else if (state->sa_mqtail->b_wptr <
18507c478bd9Sstevel@tonic-gate DB_LIM(state->sa_mqtail)) {
18517c478bd9Sstevel@tonic-gate *state->sa_mqtail->b_wptr++ = PFF |len;
18527c478bd9Sstevel@tonic-gate } else {
18537c478bd9Sstevel@tonic-gate /* allocate a new mblk & add the byte */
18547c478bd9Sstevel@tonic-gate /* write the data */
18557c478bd9Sstevel@tonic-gate if ((new_frame = allocb(1, BPRI_MED))
18567c478bd9Sstevel@tonic-gate == NULL) {
18577c478bd9Sstevel@tonic-gate freemsg(mp);
18587c478bd9Sstevel@tonic-gate return (send_frame);
18597c478bd9Sstevel@tonic-gate }
18607c478bd9Sstevel@tonic-gate *new_frame->b_wptr++ = PFF | (len);
18617c478bd9Sstevel@tonic-gate linkb(state->sa_mqtail, new_frame);
18627c478bd9Sstevel@tonic-gate }
18637c478bd9Sstevel@tonic-gate
18647c478bd9Sstevel@tonic-gate /* update proto */
18657c478bd9Sstevel@tonic-gate state->sa_proto = proto;
18667c478bd9Sstevel@tonic-gate }
18677c478bd9Sstevel@tonic-gate
18687c478bd9Sstevel@tonic-gate linkb(state->sa_mqtail, mp);
18697c478bd9Sstevel@tonic-gate state->sa_mqtail = mp;
18707c478bd9Sstevel@tonic-gate while (state->sa_mqtail->b_cont != NULL)
18717c478bd9Sstevel@tonic-gate state->sa_mqtail = state->sa_mqtail->b_cont;
18727c478bd9Sstevel@tonic-gate state->sa_mqlen += nlen;
18737c478bd9Sstevel@tonic-gate
18747c478bd9Sstevel@tonic-gate } else {
18757c478bd9Sstevel@tonic-gate state->sa_mqhead = mp;
18767c478bd9Sstevel@tonic-gate state->sa_mqlen = len + protolen + 1;
18777c478bd9Sstevel@tonic-gate state->sa_proto = proto;
18787c478bd9Sstevel@tonic-gate }
18797c478bd9Sstevel@tonic-gate
18807c478bd9Sstevel@tonic-gate if (state->sa_timeout_id == 0) {
18817c478bd9Sstevel@tonic-gate state->sa_timeout_id = qtimeout(q, spppasyn_timer, q,
18827c478bd9Sstevel@tonic-gate (drv_usectohz(state->sa_timeout_usec)));
18837c478bd9Sstevel@tonic-gate }
18847c478bd9Sstevel@tonic-gate return (send_frame);
18857c478bd9Sstevel@tonic-gate }
18867c478bd9Sstevel@tonic-gate
18877c478bd9Sstevel@tonic-gate /*
18887c478bd9Sstevel@tonic-gate * Called from receive frame, this routine checks if it is a PPP_MUX
18897c478bd9Sstevel@tonic-gate * packet and demuxes it. The returned pointer is a chain of mblks
18907c478bd9Sstevel@tonic-gate * using b_next and representing the demultiplexed packets.
18917c478bd9Sstevel@tonic-gate */
18927c478bd9Sstevel@tonic-gate static mblk_t *
spppasyn_inpkt(queue_t * q,mblk_t * mp)18937c478bd9Sstevel@tonic-gate spppasyn_inpkt(queue_t *q, mblk_t *mp)
18947c478bd9Sstevel@tonic-gate {
18957c478bd9Sstevel@tonic-gate sppp_ahdlc_t *state = (sppp_ahdlc_t *)q->q_ptr;
18967c478bd9Sstevel@tonic-gate ushort_t proto;
18977c478bd9Sstevel@tonic-gate ushort_t prev_proto;
18987c478bd9Sstevel@tonic-gate uint32_t len; /* length of subframe */
18997c478bd9Sstevel@tonic-gate uchar_t muxhdr;
19007c478bd9Sstevel@tonic-gate mblk_t *hdrmp;
19017c478bd9Sstevel@tonic-gate mblk_t *subframe;
19027c478bd9Sstevel@tonic-gate mblk_t *retmp;
19037c478bd9Sstevel@tonic-gate
19047c478bd9Sstevel@tonic-gate if (!(mp->b_rptr[0] & PFF)) {
19057c478bd9Sstevel@tonic-gate KINCR(pks_inmuxerrs);
19067c478bd9Sstevel@tonic-gate (void) putnextctl1(q, M_CTL, PPPCTL_IERROR);
19077c478bd9Sstevel@tonic-gate freemsg(mp);
19087c478bd9Sstevel@tonic-gate return (NULL);
19097c478bd9Sstevel@tonic-gate }
19107c478bd9Sstevel@tonic-gate
19117c478bd9Sstevel@tonic-gate /* initialise the Last protocol and protocol length */
19127c478bd9Sstevel@tonic-gate prev_proto = 0;
19137c478bd9Sstevel@tonic-gate
19147c478bd9Sstevel@tonic-gate /*
19157c478bd9Sstevel@tonic-gate * Taking into granted that the decoded frame is contiguous
19167c478bd9Sstevel@tonic-gate */
19177c478bd9Sstevel@tonic-gate retmp = NULL;
19187c478bd9Sstevel@tonic-gate while (mp->b_rptr < mp->b_wptr) {
19197c478bd9Sstevel@tonic-gate
19207c478bd9Sstevel@tonic-gate /*
19217c478bd9Sstevel@tonic-gate * get the last protocol, protocol length
19227c478bd9Sstevel@tonic-gate * and the length of the message
19237c478bd9Sstevel@tonic-gate */
19247c478bd9Sstevel@tonic-gate
19257c478bd9Sstevel@tonic-gate /* protocol field flag and length */
19267c478bd9Sstevel@tonic-gate muxhdr = mp->b_rptr[0];
19277c478bd9Sstevel@tonic-gate len = muxhdr & ~PFF;
19287c478bd9Sstevel@tonic-gate
19297c478bd9Sstevel@tonic-gate mp->b_rptr++;
19307c478bd9Sstevel@tonic-gate
19317c478bd9Sstevel@tonic-gate /* check if there and enough bytes left in pkt */
19327c478bd9Sstevel@tonic-gate if (MBLKL(mp) < len) {
19337c478bd9Sstevel@tonic-gate KINCR(pks_inmuxerrs);
19347c478bd9Sstevel@tonic-gate (void) putnextctl1(q, M_CTL, PPPCTL_IERROR);
19357c478bd9Sstevel@tonic-gate break;
19367c478bd9Sstevel@tonic-gate }
19377c478bd9Sstevel@tonic-gate
19387c478bd9Sstevel@tonic-gate /* allocate memory for the header length */
19397c478bd9Sstevel@tonic-gate if ((hdrmp = allocb(PPP_HDRLEN, BPRI_MED)) == NULL) {
19407c478bd9Sstevel@tonic-gate KINCR(pks_inallocfails);
19417c478bd9Sstevel@tonic-gate break;
19427c478bd9Sstevel@tonic-gate }
19437c478bd9Sstevel@tonic-gate
19447c478bd9Sstevel@tonic-gate /* add the ppp header to the pkt */
19457c478bd9Sstevel@tonic-gate *hdrmp->b_wptr++ = PPP_ALLSTATIONS;
19467c478bd9Sstevel@tonic-gate *hdrmp->b_wptr++ = PPP_UI;
19477c478bd9Sstevel@tonic-gate
19487c478bd9Sstevel@tonic-gate /* check if the protocol field flag is set */
19497c478bd9Sstevel@tonic-gate if (muxhdr & PFF) {
19507c478bd9Sstevel@tonic-gate
19517c478bd9Sstevel@tonic-gate /* get the protocol */
19527c478bd9Sstevel@tonic-gate proto = MSG_BYTE(mp, 0);
19537c478bd9Sstevel@tonic-gate if ((proto & 1) == 0)
19547c478bd9Sstevel@tonic-gate proto = (proto << 8) + MSG_BYTE(mp, 1);
19557c478bd9Sstevel@tonic-gate
19567c478bd9Sstevel@tonic-gate /* reset values */
19577c478bd9Sstevel@tonic-gate prev_proto = proto;
19587c478bd9Sstevel@tonic-gate } else {
19597c478bd9Sstevel@tonic-gate if (!IS_DECOMP_PROT(state))
19607c478bd9Sstevel@tonic-gate *hdrmp->b_wptr++ = prev_proto >> 8;
19617c478bd9Sstevel@tonic-gate *hdrmp->b_wptr++ = (prev_proto & 0xff);
19627c478bd9Sstevel@tonic-gate }
19637c478bd9Sstevel@tonic-gate
19647c478bd9Sstevel@tonic-gate /* get the payload from the MUXed packet */
19657c478bd9Sstevel@tonic-gate subframe = dupmsg(mp);
19667c478bd9Sstevel@tonic-gate subframe->b_wptr = mp->b_rptr + len;
19677c478bd9Sstevel@tonic-gate
19687c478bd9Sstevel@tonic-gate /* link the subframe to the new frame */
19697c478bd9Sstevel@tonic-gate linkb(hdrmp, subframe);
19707c478bd9Sstevel@tonic-gate
19717c478bd9Sstevel@tonic-gate /* do a putnext */
19727c478bd9Sstevel@tonic-gate retmp = sppp_mappend(retmp, hdrmp);
19737c478bd9Sstevel@tonic-gate
19747c478bd9Sstevel@tonic-gate /* move the read pointer beyond this subframe */
19757c478bd9Sstevel@tonic-gate mp->b_rptr += len;
19767c478bd9Sstevel@tonic-gate }
19777c478bd9Sstevel@tonic-gate
19787c478bd9Sstevel@tonic-gate freemsg(mp);
19797c478bd9Sstevel@tonic-gate return (retmp);
19807c478bd9Sstevel@tonic-gate }
19817c478bd9Sstevel@tonic-gate
19827c478bd9Sstevel@tonic-gate
19837c478bd9Sstevel@tonic-gate /*
19847c478bd9Sstevel@tonic-gate * timer routine which sends out the queued pkts *
19857c478bd9Sstevel@tonic-gate */
19867c478bd9Sstevel@tonic-gate static void
spppasyn_timer(void * arg)19877c478bd9Sstevel@tonic-gate spppasyn_timer(void *arg)
19887c478bd9Sstevel@tonic-gate {
19897c478bd9Sstevel@tonic-gate queue_t *q;
19907c478bd9Sstevel@tonic-gate sppp_ahdlc_t *state;
19917c478bd9Sstevel@tonic-gate mblk_t *mp;
19927c478bd9Sstevel@tonic-gate
19937c478bd9Sstevel@tonic-gate ASSERT(arg);
19947c478bd9Sstevel@tonic-gate q = (queue_t *)arg;
19957c478bd9Sstevel@tonic-gate state = (sppp_ahdlc_t *)q->q_ptr;
19967c478bd9Sstevel@tonic-gate
19977c478bd9Sstevel@tonic-gate if (state->sa_mqhead != NULL) {
19987c478bd9Sstevel@tonic-gate /* increment counter */
19997c478bd9Sstevel@tonic-gate if (state->sa_mqtail != NULL)
20007c478bd9Sstevel@tonic-gate KINCR(pks_sentmux);
20017c478bd9Sstevel@tonic-gate if ((mp = ahdlc_encode(q, state->sa_mqhead)) != NULL)
20027c478bd9Sstevel@tonic-gate putnext(q, mp);
20037c478bd9Sstevel@tonic-gate /* reset the state values over here */
20047c478bd9Sstevel@tonic-gate RESET_MUX_VALUES(state);
20057c478bd9Sstevel@tonic-gate }
20067c478bd9Sstevel@tonic-gate /* clear timeout_id */
20077c478bd9Sstevel@tonic-gate state->sa_timeout_id = 0;
20087c478bd9Sstevel@tonic-gate }
2009