2 * spppasyn.c - STREAMS module for doing PPP asynchronous HDLC.
4 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
5 * Use is subject to license terms.
6 * Copyright (c) 2016 by Delphix. All rights reserved.
8 * Permission to use, copy, modify, and distribute this software and its
9 * documentation is hereby granted, provided that the above copyright
10 * notice appears in all copies.
12 * SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF
13 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
14 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
15 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
16 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
17 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES
19 * Copyright (c) 1994 The Australian National University.
20 * All rights reserved.
22 * Permission to use, copy, modify, and distribute this software and its
23 * documentation is hereby granted, provided that the above copyright
24 * notice appears in all copies. This software is provided without any
25 * warranty, express or implied. The Australian National University
26 * makes no representations about the suitability of this software for
29 * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
30 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
31 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
32 * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY
35 * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
36 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
37 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
38 * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
39 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
42 * $Id: ppp_ahdlc.c,v 1.16 2000/03/06 19:38:12 masputra Exp $
45 #pragma ident "%Z%%M% %I% %E% SMI"
47 #include <sys/types.h>
48 #include <sys/param.h>
49 #include <sys/stream.h>
50 #include <sys/strsun.h>
51 #include <sys/sysmacros.h>
52 #include <sys/errno.h>
55 #include <sys/crc32.h>
56 #include <sys/cmn_err.h>
59 #include <net/ppp_defs.h>
60 #include <net/pppio.h>
65 #define REPORT_CRC_TYPE
70 * This is used to tag official Solaris sources. Please do not define
71 * "INTERNAL_BUILD" when building this software outside of Sun
75 /* MODINFO is limited to 32 characters. */
76 const char spppasyn_module_description
[] = "PPP 4.0 AHDLC";
77 #else /* INTERNAL_BUILD */
78 const char spppasyn_module_description
[] = "ANU PPP AHDLC $Revision: 1.16$";
81 static const char buildtime
[] = "Built " __DATE__
" at " __TIME__
86 #endif /* INTERNAL_BUILD */
88 static int spppasyn_open(queue_t
*, dev_t
*, int, int, cred_t
*);
89 static int spppasyn_close(queue_t
*, int, cred_t
*);
90 static int spppasyn_wput(queue_t
*, mblk_t
*);
91 static int spppasyn_rput(queue_t
*, mblk_t
*);
92 static mblk_t
*ahdlc_encode(queue_t
*, mblk_t
*);
93 static mblk_t
*ahdlc_decode(queue_t
*, mblk_t
*);
94 static void spppasyn_timer(void *);
95 static mblk_t
*spppasyn_inpkt(queue_t
*, mblk_t
*);
96 static mblk_t
*spppasyn_muxencode(queue_t
*, mblk_t
*);
98 #define RESET_MUX_VALUES(x) { \
99 x->sa_mqhead = x->sa_mqtail = NULL; \
103 #define IS_XMUX_ENABLED(x) \
104 ((x)->sa_flags & X_MUXMASK)
105 #define IS_RMUX_ENABLED(x) \
106 ((x)->sa_flags & R_MUXMASK)
107 #define IS_COMP_AC(x) \
108 ((x)->sa_flags & SAF_XCOMP_AC)
109 #define IS_COMP_PROT(x) \
110 ((x)->sa_flags & SAF_XCOMP_PROT)
111 #define IS_DECOMP_PROT(x) \
112 ((x)->sa_flags & SAF_RDECOMP_PROT)
115 * Don't send HDLC start flag if last transmit is within 1.5 seconds -
116 * FLAG_TIME is defined in nanoseconds.
118 #define FLAG_TIME 1500000000ul
121 * The usual AHDLC implementation enables the default escaping for all
122 * LCP frames. LCP_USE_DFLT() is used in this implementation to
123 * modify this rule slightly. If the code number happens to be
124 * Echo-Request, Echo-Reply, or Discard-Request (each of which may be
125 * sent only when LCP is in Opened state), then one may also use the
126 * negotiated ACCM; the RFC is silent on this. The theory is that
127 * pppd can construct Echo-Request messages that are guaranteed to
128 * fail if the negotiated ACCM is bad.
130 #define LCP_USE_DFLT(mp) ((code = MSG_BYTE((mp), 4)) < 9 || code > 11)
133 * Extract bit c from map m, to determine if character c needs to be
134 * escaped. Map 'm' is a pointer to a 256 bit map; 8 words of 32 bits
137 #define IN_TX_MAP(c, m) \
138 ((m)[(c) >> 5] & (1 << ((c) & 0x1f)))
141 * Checks the 32-bit receive ACCM to see if the byte should have been
144 #define IN_RX_MAP(c, m) (((c) < 0x20) && ((m) & (1 << (c))))
146 static struct module_info spppasyn_modinfo
= {
147 AHDLC_MOD_ID
, /* mi_idnum */
148 AHDLC_MOD_NAME
, /* mi_idname */
150 INFPSZ
, /* mi_maxpsz */
155 static struct qinit spppasyn_rinit
= {
156 spppasyn_rput
, /* qi_putp */
158 spppasyn_open
, /* qi_qopen */
159 spppasyn_close
, /* qi_qclose */
160 NULL
, /* qi_qadmin */
161 &spppasyn_modinfo
, /* qi_minfo */
165 static struct qinit spppasyn_winit
= {
166 spppasyn_wput
, /* qi_putp */
169 NULL
, /* qi_qclose */
170 NULL
, /* qi_qadmin */
171 &spppasyn_modinfo
, /* qi_minfo */
175 struct streamtab spppasyn_tab
= {
176 &spppasyn_rinit
, /* st_rdinit */
177 &spppasyn_winit
, /* st_wrinit */
178 NULL
, /* st_muxrinit */
179 NULL
, /* st_muxwinit */
182 /* Matches above structure. */
183 static const char *kstat_names
[] = {
184 "ioctls", "ioctlsfwd", "ioctlserr", "ctls",
185 "ctlsfwd", "ctlserr", "inbadchars", "inbadcharmask",
186 "inaborts", "inrunts", "inallocfails", "intoolongs",
187 "outrunts", "outallocfails", "incrcerrs", "unknownwrs",
188 "unknownrds", "hangups", "datain", "dataout",
189 "extrabufs", "sentmux", "recvmux", "inmuxerrs",
190 #ifdef REPORT_CRC_TYPE
191 "incrctype", "outcrctype",
195 /* So. This is why we have optimizing compilers. */
196 #define KVAL(vn) state->sa_kstats.vn.value.ui32
197 #define KSET(vn, v) KVAL(vn) = (v)
198 #define KADD(vn, v) KSET(vn, KVAL(vn) + (v))
199 #define KOR(vn, v) KSET(vn, KVAL(vn) | (v))
200 #define KINCR(vn) KADD(vn, 1)
202 static void ppp_dump_frame(sppp_ahdlc_t
*state
, mblk_t
*mptr
,
206 * RCV_B7_1, etc., defined in net/pppio.h, are stored in flags also.
208 #define RCV_FLAGS (RCV_B7_1 | RCV_B7_0 | RCV_ODDP | RCV_EVNP)
211 * FCS lookup table as calculated by genfcstab.
213 static ushort_t fcstab
[256] = {
214 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
215 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
216 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
217 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
218 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
219 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
220 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
221 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
222 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
223 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
224 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
225 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
226 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
227 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
228 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
229 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
230 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
231 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
232 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
233 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
234 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
235 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
236 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
237 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
238 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
239 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
240 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
241 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
242 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
243 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
244 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
245 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
249 * Per-character flags for accumulating input errors. Flags are
250 * accumulated for bit 7 set to 0, bit 7 set to 1, even parity
251 * characters, and odd parity characters. The link should see all
252 * four in the very first LCP Configure-Request if all is ok. (C0 is
253 * even parity and has bit 7 set to 1, and 23 is odd parity and has
256 static uchar_t charflags
[256] = {
257 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_ODDP
,
258 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_EVNP
,
259 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_ODDP
,
260 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
,
261 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_ODDP
,
262 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_EVNP
,
263 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_EVNP
,
264 RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_EVNP
,
265 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_ODDP
,
266 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_EVNP
,
267 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_ODDP
,
268 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
,
269 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_ODDP
,
270 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
,
271 RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
,
272 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
,
273 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_ODDP
,
274 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_EVNP
,
275 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_ODDP
,
276 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
,
277 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_ODDP
,
278 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_EVNP
,
279 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_EVNP
,
280 RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_EVNP
,
281 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_ODDP
,
282 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_EVNP
,
283 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_EVNP
,
284 RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_EVNP
,
285 RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_EVNP
,
286 RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_EVNP
,
287 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_EVNP
,
288 RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_EVNP
,
289 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_ODDP
,
290 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_EVNP
,
291 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_ODDP
,
292 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
,
293 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_ODDP
,
294 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_EVNP
,
295 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_EVNP
,
296 RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_EVNP
,
297 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_ODDP
,
298 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_0
|RCV_EVNP
,
299 RCV_B7_0
|RCV_EVNP
, RCV_B7_0
|RCV_ODDP
, RCV_B7_1
|RCV_ODDP
,
300 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
,
301 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
, RCV_B7_1
|RCV_ODDP
,
302 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
,
303 RCV_B7_1
|RCV_ODDP
, RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
,
304 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
,
305 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
, RCV_B7_1
|RCV_ODDP
,
306 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
, RCV_B7_1
|RCV_EVNP
,
307 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
, RCV_B7_1
|RCV_ODDP
,
308 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
,
309 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
, RCV_B7_1
|RCV_ODDP
,
310 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
,
311 RCV_B7_1
|RCV_ODDP
, RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
,
312 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
,
313 RCV_B7_1
|RCV_ODDP
, RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_EVNP
,
314 RCV_B7_1
|RCV_ODDP
, RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
,
315 RCV_B7_1
|RCV_ODDP
, RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
,
316 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
,
317 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
, RCV_B7_1
|RCV_ODDP
,
318 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
,
319 RCV_B7_1
|RCV_ODDP
, RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
,
320 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
,
321 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
, RCV_B7_1
|RCV_ODDP
,
322 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
, RCV_B7_1
|RCV_EVNP
,
323 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
, RCV_B7_1
|RCV_ODDP
,
324 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
,
325 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
, RCV_B7_1
|RCV_ODDP
,
326 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
, RCV_B7_1
|RCV_EVNP
,
327 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
, RCV_B7_1
|RCV_EVNP
,
328 RCV_B7_1
|RCV_ODDP
, RCV_B7_1
|RCV_ODDP
, RCV_B7_1
|RCV_EVNP
,
329 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
, RCV_B7_1
|RCV_ODDP
,
330 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
, RCV_B7_1
|RCV_EVNP
,
331 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
, RCV_B7_1
|RCV_ODDP
,
332 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
,
333 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
, RCV_B7_1
|RCV_ODDP
,
334 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
,
335 RCV_B7_1
|RCV_ODDP
, RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
,
336 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
,
337 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
, RCV_B7_1
|RCV_ODDP
,
338 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
, RCV_B7_1
|RCV_EVNP
,
339 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
, RCV_B7_1
|RCV_ODDP
,
340 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
,
341 RCV_B7_1
|RCV_EVNP
, RCV_B7_1
|RCV_ODDP
, RCV_B7_1
|RCV_ODDP
,
346 * Append two lists; preserve message boundaries.
347 * Warning: uses b_next.
350 sppp_mappend(mblk_t
*m1
, mblk_t
*m2
)
360 while (m1
->b_next
!= NULL
)
367 * Concatenate two mblk lists.
370 sppp_mcat(mblk_t
*m1
, mblk_t
*m2
)
380 while (m1
->b_cont
!= NULL
)
389 * STREAMS module open (entry) point. Called when spppasyn is pushed
390 * onto an asynchronous serial stream.
394 spppasyn_open(queue_t
*q
, dev_t
*devp
, int flag
, int sflag
, cred_t
*credp
)
400 if (q
->q_ptr
!= NULL
) {
401 return (0); /* return if already opened */
404 if (sflag
!= MODOPEN
) {
405 return (EINVAL
); /* only open as a module */
408 state
= (sppp_ahdlc_t
*)kmem_zalloc(sizeof (sppp_ahdlc_t
), KM_SLEEP
);
409 ASSERT(state
!= NULL
);
411 q
->q_ptr
= (caddr_t
)state
;
412 WR(q
)->q_ptr
= (caddr_t
)state
;
414 state
->sa_xaccm
[0] = 0xffffffff; /* escape 0x00 through 0x1f */
415 state
->sa_xaccm
[3] = 0x60000000; /* escape 0x7d and 0x7e */
416 state
->sa_mru
= PPP_MRU
; /* default of 1500 bytes */
426 * STREAMS module close (exit) point
430 spppasyn_close(queue_t
*q
, int flag
, cred_t
*credp
)
435 state
= (sppp_ahdlc_t
*)q
->q_ptr
;
436 ASSERT(state
!= NULL
);
438 /* We're leaving now. No more calls, please. */
441 if (state
->sa_rx_buf
!= NULL
) {
442 freemsg(state
->sa_rx_buf
);
443 state
->sa_rx_buf
= NULL
;
446 if (state
->sa_ksp
!= NULL
) {
447 kstat_delete(state
->sa_ksp
);
448 state
->sa_ksp
= NULL
;
451 if (state
->sa_mqhead
!= NULL
)
452 freemsg(state
->sa_mqhead
);
453 /* remove the time out routine */
454 if (state
->sa_timeout_id
!= 0)
455 (void) quntimeout(q
, state
->sa_timeout_id
);
459 kmem_free(state
, sizeof (sppp_ahdlc_t
));
465 * Create the standard kernel statistics structure and attach it to
466 * the current state structure. This can be called only after
467 * assigning the unit number.
470 create_kstats(sppp_ahdlc_t
*state
)
473 char unitname
[KSTAT_STRLEN
];
477 nstat
= sizeof (state
->sa_kstats
) / sizeof (kstat_named_t
);
478 knt
= (kstat_named_t
*)&state
->sa_kstats
;
479 for (i
= 0; i
< nstat
; i
++, knt
++) {
481 /* Just in case I do something silly here. */
482 if (i
>= sizeof (kstat_names
) / sizeof (kstat_names
[0]))
483 (void) sprintf(knt
->name
, "unknown%d", i
);
486 (void) strncpy(knt
->name
, kstat_names
[i
],
488 knt
->data_type
= KSTAT_DATA_UINT32
;
491 * sprintf is known to be safe here because KSTAT_STRLEN is
492 * 31, the maximum module name length is 8, and the maximum
493 * string length from %d is 11. This was once snprintf, but
494 * that's not backward-compatible with Solaris 2.6.
496 (void) sprintf(unitname
, "%s" "%d", AHDLC_MOD_NAME
, state
->sa_unit
);
497 ksp
= kstat_create(AHDLC_MOD_NAME
, state
->sa_unit
, unitname
, "net",
498 KSTAT_TYPE_NAMED
, nstat
, KSTAT_FLAG_VIRTUAL
);
500 ksp
->ks_data
= (void *)&state
->sa_kstats
;
504 #ifdef REPORT_CRC_TYPE
505 KSET(pks_outcrctype
, 16);
506 KSET(pks_incrctype
, 16);
511 * spppasyn_inner_ioctl
516 * Handle state-affecting ioctls.
519 spppasyn_inner_ioctl(queue_t
*q
, mblk_t
*mp
)
530 ASSERT(q
!= NULL
&& mp
!= NULL
);
531 state
= (sppp_ahdlc_t
*)q
->q_ptr
;
532 iop
= (struct iocblk
*)mp
->b_rptr
;
533 ASSERT(state
!= NULL
&& iop
!= NULL
);
538 switch (iop
->ioc_cmd
) {
540 /* Check for valid option length */
541 if (iop
->ioc_count
!= sizeof (uint32_t) || mp
->b_cont
== NULL
)
544 /* Grab flag value */
545 flagval
= *(uint32_t *)mp
->b_cont
->b_rptr
;
546 if (flagval
< PPPFCS_16
|| flagval
> PPPFCS_NONE
)
548 state
->sa_flags
&= ~SAF_XMITCRC32
& ~SAF_XMITCRCNONE
;
549 if (flagval
== PPPFCS_32
) {
550 #ifdef REPORT_CRC_TYPE
551 KSET(pks_outcrctype
, 32);
553 state
->sa_flags
|= SAF_XMITCRC32
;
554 } else if (flagval
== PPPFCS_NONE
) {
555 #ifdef REPORT_CRC_TYPE
556 KSET(pks_outcrctype
, 0);
558 state
->sa_flags
|= SAF_XMITCRCNONE
;
560 #ifdef REPORT_CRC_TYPE
562 KSET(pks_outcrctype
, 16);
571 /* Check for valid option length */
572 if (iop
->ioc_count
!= sizeof (uint32_t) || mp
->b_cont
== NULL
)
575 /* Grab flag value */
576 flagval
= *(uint32_t *)mp
->b_cont
->b_rptr
;
577 if (flagval
< PPPFCS_16
|| flagval
> PPPFCS_NONE
)
579 state
->sa_flags
&= ~SAF_RECVCRC32
& ~SAF_RECVCRCNONE
;
580 if (flagval
== PPPFCS_32
) {
581 #ifdef REPORT_CRC_TYPE
582 KSET(pks_incrctype
, 32);
584 state
->sa_flags
|= SAF_RECVCRC32
;
585 } else if (flagval
== PPPFCS_NONE
) {
586 #ifdef REPORT_CRC_TYPE
587 KSET(pks_incrctype
, 0);
589 state
->sa_flags
|= SAF_RECVCRCNONE
;
591 #ifdef REPORT_CRC_TYPE
593 KSET(pks_incrctype
, 16);
602 /* Check for valid asyncmap length */
603 if (iop
->ioc_count
< sizeof (uint32_t) ||
604 iop
->ioc_count
> sizeof (ext_accm
) ||
608 /* Copy user's asyncmap into our state structure. */
609 bcopy((caddr_t
)mp
->b_cont
->b_rptr
,
610 (caddr_t
)state
->sa_xaccm
, iop
->ioc_count
);
612 state
->sa_xaccm
[2] &= ~0x40000000; /* don't escape 0x5e */
613 state
->sa_xaccm
[3] |= 0x60000000; /* escape 0x7d, 0x7e */
619 /* Check for valid asyncmap length (only ctrl chars) */
620 if (iop
->ioc_count
!= sizeof (uint32_t) ||
624 state
->sa_raccm
= *(uint32_t *)mp
->b_cont
->b_rptr
;
630 /* We already know this. */
631 state
->sa_flags
|= SAF_LASTMOD
;
636 /* set the compression flags */
637 if (iop
->ioc_count
!= 2 * sizeof (uint32_t) ||
641 /* set the mux flags */
642 mux_flags
= ((uint32_t *)mp
->b_cont
->b_rptr
)[0];
643 mask
= ((uint32_t *)mp
->b_cont
->b_rptr
)[1];
645 state
->sa_flags
= (state
->sa_flags
& ~mask
) | (mask
);
647 /* set the multiplexing timer value */
648 if (mask
& R_MUXMASK
)
649 state
->sa_timeout_usec
= mux_flags
;
655 if (iop
->ioc_count
!= 2 * sizeof (uint32_t) ||
659 flagval
= (((uint32_t *)mp
->b_cont
->b_rptr
)[0] << 20) &
660 (SAF_RDECOMP_PROT
| SAF_RDECOMP_AC
| SAF_XCOMP_PROT
|
662 flagmask
= (((uint32_t *)mp
->b_cont
->b_rptr
)[1] << 20) &
663 (SAF_RDECOMP_PROT
| SAF_RDECOMP_AC
| SAF_XCOMP_PROT
|
665 state
->sa_flags
= flagval
| (state
->sa_flags
& ~flagmask
);
666 *(uint32_t *)mp
->b_cont
->b_rptr
= state
->sa_flags
>> 20;
667 len
= sizeof (uint32_t);
672 if (iop
->ioc_count
!= sizeof (uint32_t) || mp
->b_cont
== NULL
)
675 flagval
= *(uint32_t *)mp
->b_cont
->b_rptr
;
676 if (flagval
!= PPPDBG_LOG
+ PPPDBG_AHDLC
) {
680 cmn_err(CE_CONT
, AHDLC_MOD_NAME
"%d: debug log enabled\n",
682 state
->sa_flags
|= SAF_XMITDUMP
| SAF_RECVDUMP
;
688 /* Success; tell the user */
689 if (mp
->b_cont
== NULL
)
692 mp
->b_cont
->b_wptr
= mp
->b_cont
->b_rptr
+ len
;
693 miocack(q
, mp
, len
, 0);
695 /* Failure; send error back upstream. */
696 KINCR(pks_ioctlserr
);
697 miocnak(q
, mp
, 0, error
);
702 * spppasyn_inner_mctl
707 * Handle state-affecting M_CTL messages.
710 spppasyn_inner_mctl(queue_t
*q
, mblk_t
*mp
)
716 ASSERT(q
!= NULL
&& mp
!= NULL
);
717 state
= (sppp_ahdlc_t
*)q
->q_ptr
;
718 ASSERT(state
!= NULL
);
722 switch (*mp
->b_rptr
) {
724 /* Just ignore the MTU */
732 ((ushort_t
*)mp
->b_rptr
)[1];
736 if (state
->sa_ksp
!= NULL
) {
741 state
->sa_unit
= mp
->b_rptr
[1];
742 else if (msglen
== 8)
744 ((uint32_t *)mp
->b_rptr
)[1];
747 if (error
== 0 && state
->sa_ksp
== NULL
)
748 create_kstats(state
);
755 if (state
->sa_flags
& SAF_LASTMOD
) {
769 * Write side put routine. This called by the modules above us (likely to
770 * be the compression module) to transmit data or pass along ioctls.
773 spppasyn_wput(queue_t
*q
, mblk_t
*mp
)
779 struct ppp_stats64
*psp
;
782 ASSERT(q
!= NULL
&& mp
!= NULL
);
783 state
= (sppp_ahdlc_t
*)q
->q_ptr
;
784 ASSERT(state
!= NULL
);
790 * A data packet - do character-stuffing and FCS, and
791 * send it onwards. The blocks are freed as we go.
793 if (IS_XMUX_ENABLED(state
))
794 mp
= spppasyn_muxencode(q
, mp
);
796 mp
= ahdlc_encode(q
, mp
);
804 iop
= (struct iocblk
*)mp
->b_rptr
;
808 switch (iop
->ioc_cmd
) {
817 spppasyn_inner_ioctl(q
, mp
);
821 np
= allocb(sizeof (uint32_t), BPRI_HI
);
826 if (mp
->b_cont
!= NULL
) {
831 *(uint32_t *)np
->b_wptr
= state
->sa_flags
& RCV_FLAGS
;
833 msglen
= sizeof (uint32_t);
834 np
->b_wptr
+= msglen
;
842 case PPPIO_GETSTAT64
:
843 np
= allocb(sizeof (*psp
), BPRI_HI
);
848 if (mp
->b_cont
!= NULL
) {
853 psp
= (struct ppp_stats64
*)np
->b_wptr
;
854 bzero((caddr_t
)psp
, sizeof (*psp
));
855 psp
->p
= state
->sa_stats
;
857 msglen
= sizeof (*psp
);
858 np
->b_wptr
+= msglen
;
863 np
= allocb(sizeof (uint32_t), BPRI_HI
);
868 if (mp
->b_cont
!= NULL
) {
873 *(uint32_t *)np
->b_wptr
= PPPTYP_AHDLC
;
875 msglen
= sizeof (uint32_t);
876 np
->b_wptr
+= msglen
;
881 /* Unknown ioctl -- forward along */
882 KINCR(pks_ioctlsfwd
);
888 /* Success; tell the user */
889 miocack(q
, mp
, msglen
, 0);
891 /* Failure; send error back upstream. */
892 KINCR(pks_ioctlserr
);
893 miocnak(q
, mp
, 0, error
);
900 spppasyn_inner_mctl(q
, mp
);
904 if (state
->sa_flags
& (SAF_XMITDUMP
|SAF_RECVDUMP
))
906 "spppasyn_wpur: unknown buffer type %d",
908 KINCR(pks_unknownwrs
);
922 * Read side put routine. This is called by the async serial driver
923 * below us to handle received data and returned signals (like
927 spppasyn_rput(queue_t
*q
, mblk_t
*mp
)
932 ASSERT(q
!= NULL
&& mp
!= NULL
);
933 state
= (sppp_ahdlc_t
*)q
->q_ptr
;
934 ASSERT(state
!= NULL
);
939 /* Note -- decoder frees the buffers */
940 mp
= ahdlc_decode(q
, mp
);
951 state
->sa_flags
|= SAF_IFLUSH
;
956 if (state
->sa_flags
& (SAF_XMITDUMP
|SAF_RECVDUMP
)) {
957 if (MTYPE(mp
) == M_IOCTL
)
959 "spppasyn_rput: unexpected ioctl %X",
960 ((struct iocblk
*)mp
->b_rptr
)->ioc_cmd
);
963 "spppasyn_rput: unknown buffer type %d",
966 KINCR(pks_unknownrds
);
977 * Perform asynchronous HDLC framing on a given buffer and transmit
978 * the result. The state structure must be valid. The input buffers
979 * are freed as we go.
981 * This function is called by wput and just encodes the data. Wput
982 * then calls putnext directly. There's no service routine for this
983 * module, so flow control is asserted by the module below us up to
984 * our caller by the STREAMS framework. This is by design -- this
985 * module does not queue anything so that other modules can make QoS
989 ahdlc_encode(queue_t
*q
, mblk_t
*mp
)
992 uint32_t loc_xaccm
[8];
1004 int chr
; /* not uchar_t; more efficient this way */
1005 /* with WorkShop compiler */
1006 int is_lcp
, is_ctrl
;
1009 uint32_t flags
; /* sampled copy of flags */
1011 state
= (sppp_ahdlc_t
*)q
->q_ptr
;
1013 /* Don't transmit anything obviously silly. */
1014 msglen
= msgsize(mp
);
1016 KINCR(pks_outrunts
);
1018 (void) putnextctl1(RD(q
), M_CTL
, PPPCTL_OERROR
);
1023 * Allocate an output buffer just large enough for most cases.
1024 * Based on original work in the ppp-2.2 AIX PPP driver, we
1025 * estimate the output size as 1.25 * input message length
1026 * plus 16. If this turns out to be too small, then we'll
1027 * allocate exactly one additional buffer with two times the
1028 * remaining input length (the maximum that could possibly be
1031 outmp_len
= msglen
+ (msglen
>> 2) + 16;
1032 outmp
= allocb(outmp_len
, BPRI_MED
);
1039 * Check if our last transmit happened within FLAG_TIME, using
1040 * the system's hrtime.
1042 hrtime
= gethrtime();
1043 if (ABS(hrtime
- state
->sa_hrtime
) > FLAG_TIME
) {
1046 state
->sa_hrtime
= hrtime
;
1047 bcopy((caddr_t
)state
->sa_xaccm
, (caddr_t
)loc_xaccm
, sizeof (loc_xaccm
));
1048 flags
= state
->sa_flags
;
1051 * LCP messages must be sent using the default escaping
1052 * (ACCM). We bend this rule a little to allow LCP
1053 * Echo-Request through with the negotiated escaping so that
1054 * we can detect bad negotiated ACCM values. If the ACCM is
1055 * bad, echos will fail and take down the link.
1057 is_lcp
= is_ctrl
= 0;
1058 code
= MSG_BYTE(mp
, 0);
1059 if (code
== PPP_ALLSTATIONS
) {
1060 if (MSG_BYTE(mp
, 1) == PPP_UI
) {
1061 code
= MSG_BYTE(mp
, 2);
1062 if (code
== (PPP_LCP
>> 8) &&
1063 MSG_BYTE(mp
, 3) == (PPP_LCP
& 0xFF)) {
1064 if (LCP_USE_DFLT(mp
))
1067 is_lcp
= 1; /* Echo-Request */
1068 } else if (!(code
& 1) && code
> 0x3F)
1071 } else if (!(code
& 1) && code
> 0x3F)
1075 * If it's LCP and not just an LCP Echo-Request, then we need
1076 * to drop back to default escaping rules temporarily.
1080 * force escape on 0x00 through 0x1f
1081 * and, for RFC 1662 (and ISO 3309:1991), 0x80-0x9f.
1083 loc_xaccm
[0] = 0xffffffff;
1084 loc_xaccm
[4] = 0xffffffff;
1087 fcs16
= PPPINITFCS16
; /* Initial FCS is 0xffff */
1088 fcs32
= PPPINITFCS32
;
1091 * Process this block and the rest (if any) attached to this
1092 * one. Note that we quite intentionally ignore the type of
1093 * the buffer. The caller has checked that the first buffer
1094 * is M_DATA; all others must be so, and any that are not are
1095 * harmless driver errors.
1098 tpmax
= outmp
->b_datap
->db_lim
;
1101 while (dp
< (ep
= mp
->b_wptr
)) {
1103 * Calculate maximum safe run length for inner loop,
1104 * regardless of escaping.
1106 outmp_len
= (tpmax
- tp
) / 2;
1107 if (dp
+ outmp_len
< ep
)
1108 ep
= dp
+ outmp_len
;
1111 * Select out on CRC type here to make the
1112 * inner byte loop more efficient. (We could
1113 * do both CRCs at all times if we wanted, but
1114 * that ends up taking an extra 8 cycles per
1115 * byte -- 47% overhead!)
1117 if (flags
& SAF_XMITCRC32
) {
1120 fcs32
= PPPFCS32(fcs32
, chr
);
1121 if (IN_TX_MAP(chr
, loc_xaccm
)) {
1130 fcs16
= PPPFCS16(fcs16
, chr
);
1131 if (IN_TX_MAP(chr
, loc_xaccm
)) {
1140 * If we limited our run length and we're now low
1141 * on output space, then allocate a new output buffer.
1142 * This should rarely happen, unless the output data
1143 * has a lot of escapes.
1145 if (ep
!= mp
->b_wptr
&& tpmax
- tp
< 5) {
1146 KINCR(pks_extrabufs
);
1147 /* Get remaining message length */
1148 outmp_len
= (mp
->b_wptr
- dp
) +
1149 msgsize(mp
->b_cont
);
1150 /* Calculate maximum required space */
1151 outmp_len
= (outmp_len
+ PPP_FCS32LEN
) * 2 + 1;
1152 curout
= allocb(outmp_len
, BPRI_MED
);
1153 if ((outmp
->b_cont
= curout
) == NULL
)
1156 tp
= curout
->b_wptr
;
1157 tpmax
= curout
->b_datap
->db_lim
;
1163 } while (mp
!= NULL
);
1166 * Make sure we have enough remaining room to add the CRC (if
1167 * any) and a trailing flag byte.
1169 outmp_len
= PPP_FCS32LEN
* 2 + 1;
1170 if (tpmax
- tp
< outmp_len
) {
1171 KINCR(pks_extrabufs
);
1172 curout
= allocb(outmp_len
, BPRI_MED
);
1173 if ((outmp
->b_cont
= curout
) == NULL
)
1176 tp
= curout
->b_wptr
;
1177 tpmax
= curout
->b_datap
->db_lim
;
1181 * Network layer data is the only thing that can be sent with
1184 if ((flags
& SAF_XMITCRCNONE
) && !is_lcp
&& !is_ctrl
)
1187 if (!(flags
& SAF_XMITCRC32
))
1191 * Append the HDLC FCS, making sure that escaping is done on any
1192 * necessary bytes. Note that the FCS bytes are in little-endian.
1196 if (IN_TX_MAP(chr
, loc_xaccm
)) {
1202 chr
= (fcs32
>> 8) & 0xff;
1203 if (IN_TX_MAP(chr
, loc_xaccm
)) {
1209 if (flags
& SAF_XMITCRC32
) {
1210 chr
= (fcs32
>> 16) & 0xff;
1211 if (IN_TX_MAP(chr
, loc_xaccm
)) {
1217 chr
= (fcs32
>> 24) & 0xff;
1218 if (IN_TX_MAP(chr
, loc_xaccm
)) {
1227 * And finally append the HDLC flag, and send it away
1231 curout
->b_wptr
= tp
;
1233 state
->sa_stats
.ppp_obytes
+= msgsize(outmp
);
1234 state
->sa_stats
.ppp_opackets
++;
1236 if (state
->sa_flags
& SAF_XMITDUMP
)
1237 ppp_dump_frame(state
, outmp
, "sent");
1243 KINCR(pks_outallocfails
);
1244 state
->sa_stats
.ppp_oerrors
++;
1247 (void) putnextctl1(RD(q
), M_CTL
, PPPCTL_OERROR
);
1252 * Handle end-of-frame excitement. This is here mostly because the Solaris
1253 * C style rules require tab for indent and prohibit excessive indenting.
1256 receive_frame(queue_t
*q
, mblk_t
*outmp
, ushort_t fcs16
, uint32_t fcs32
)
1258 sppp_ahdlc_t
*state
= (sppp_ahdlc_t
*)q
->q_ptr
;
1260 int is_lcp
, is_ctrl
, crclen
;
1265 if (cp
[0] == PPP_ALLSTATIONS
&& cp
[1] == PPP_UI
)
1268 if ((proto
& 1) == 0)
1269 proto
= (proto
<< 8) + *cp
++;
1270 is_lcp
= (proto
== PPP_LCP
);
1271 is_ctrl
= (proto
>= 0x4000);
1274 * To allow for renegotiation, LCP accepts good CRCs of either
1275 * type at any time. Other control (non-network) packets must
1276 * have either CRC-16 or CRC-32, as negotiated. Network layer
1277 * packets may additionally omit the CRC entirely, if that was
1280 if ((is_lcp
&& (fcs16
== PPPGOODFCS16
|| fcs32
== PPPGOODFCS32
)) ||
1281 ((fcs16
== PPPGOODFCS16
&& !(state
->sa_flags
& SAF_RECVCRC32
)) ||
1282 (fcs32
== PPPGOODFCS32
&&
1283 (state
->sa_flags
& SAF_RECVCRC32
))) ||
1284 (!is_ctrl
&& !is_lcp
&& (state
->sa_flags
& SAF_RECVCRCNONE
))) {
1286 state
->sa_stats
.ppp_ipackets
++;
1288 crclen
= (fcs16
== PPPGOODFCS16
) ?
1289 PPP_FCSLEN
: PPP_FCS32LEN
;
1291 crclen
= (state
->sa_flags
& SAF_RECVCRC32
) ?
1292 PPP_FCS32LEN
: PPP_FCSLEN
;
1293 if (!is_ctrl
&& (state
->sa_flags
& SAF_RECVCRCNONE
))
1297 i
= adjmsg(outmp
, -crclen
);
1301 if (proto
== PPP_MUX
) {
1302 /* spppasyn_inpkt checks for PPP_MUX packets */
1304 /* Remove headers */
1306 return (spppasyn_inpkt(q
, outmp
));
1310 * Sniff the received data stream. If we see an LCP
1311 * Configure-Ack, then pick out the ACCM setting, if
1312 * any, and configure now. This allows us to stay in
1313 * sync in case the peer is already out of Establish
1316 if (is_lcp
&& *cp
== 2) {
1318 i
= (cp
[2] << 8) | cp
[3];
1320 ep
= cp
; /* Discard junk */
1321 else if (i
< ep
- cp
)
1324 while (cp
+ 2 < ep
) {
1325 if ((i
= cp
[1]) < 2)
1329 if (cp
[0] == 2 && i
>= 6) {
1330 state
->sa_raccm
= (cp
[2] << 24) |
1331 (cp
[3] << 16) | (cp
[4] << 8) |
1340 KINCR(pks_incrcerrs
);
1341 cmn_err(CE_CONT
, PPP_DRV_NAME
"%d: bad fcs (len=%ld)\n",
1342 state
->sa_unit
, msgsize(outmp
));
1344 if (state
->sa_flags
& SAF_RECVDUMP
)
1345 ppp_dump_frame(state
, outmp
, "bad data");
1349 state
->sa_stats
.ppp_ierrors
++;
1351 (void) putnextctl1(q
, M_CTL
, PPPCTL_IERROR
);
1359 * Process received characters.
1361 * This is handled as exclusive inner so that we don't get confused
1362 * about the state. Returns a list of packets linked by b_next.
1365 ahdlc_decode(queue_t
*q
, mblk_t
*mp
)
1367 sppp_ahdlc_t
*state
;
1368 mblk_t
*retmp
; /* list of packets to return */
1369 mblk_t
*outmp
; /* buffer for decoded data */
1370 mblk_t
*mpnext
; /* temporary ptr for unlinking */
1371 uchar_t
*dp
; /* pointer to input data */
1372 uchar_t
*dpend
; /* end of input data */
1373 uchar_t
*tp
; /* pointer to decoded output data */
1374 uchar_t
*tpmax
; /* output buffer limit */
1375 int flagtmp
; /* temporary cache of flags */
1376 int chr
; /* not uchar_t; more efficient this way */
1377 /* with WorkShop compiler */
1378 ushort_t fcs16
; /* running CRC-16 */
1379 uint32_t fcs32
; /* running CRC-32 */
1380 #ifdef HANDLE_ZERO_LENGTH
1384 state
= (sppp_ahdlc_t
*)q
->q_ptr
;
1388 state
->sa_stats
.ppp_ibytes
+= msgsize(mp
);
1390 if (state
->sa_flags
& SAF_RECVDUMP
)
1391 ppp_dump_frame(state
, mp
, "rcvd");
1393 flagtmp
= state
->sa_flags
;
1394 fcs16
= state
->sa_infcs16
;
1395 fcs32
= state
->sa_infcs32
;
1396 outmp
= state
->sa_rx_buf
;
1397 if (outmp
== NULL
) {
1401 tpmax
= outmp
->b_datap
->db_lim
;
1403 #ifdef HANDLE_ZERO_LENGTH
1408 * Main input processing loop. Loop over received buffers and
1409 * each byte in each buffer. Note that we quite intentionally
1410 * ignore the type of the buffer. The caller has checked that
1411 * the first buffer is M_DATA; all others must be so, and any
1412 * that are not are harmless driver errors.
1415 while (mp
!= NULL
) {
1417 /* Innermost loop -- examine bytes in buffer. */
1420 #ifdef HANDLE_ZERO_LENGTH
1421 nprocessed
+= dpend
- dp
;
1423 for (; dp
< dpend
; dp
++) {
1427 * This should detect the lack of an 8-bit
1428 * communication channel, which is necessary
1431 flagtmp
|= charflags
[chr
];
1434 * So we have a HDLC flag ...
1436 if (chr
== PPP_FLAG
) {
1439 * If there's no received buffer, then
1440 * just ignore this frame marker.
1442 if ((flagtmp
& SAF_IFLUSH
) || outmp
== NULL
) {
1443 flagtmp
&= ~SAF_IFLUSH
& ~SAF_ESCAPED
;
1448 * Per RFC 1662 -- silently discard
1449 * runt frames (fewer than 4 octets
1450 * with 16 bit CRC) and frames that
1451 * end in 7D 7E (abort sequence).
1452 * These are not counted as errors.
1454 * (We could just reset the pointers
1455 * and reuse the buffer, but this is a
1456 * rarely used error path and not
1457 * worth the optimization.)
1459 if ((flagtmp
& SAF_ESCAPED
) ||
1460 tp
- outmp
->b_rptr
< 2 + PPP_FCSLEN
) {
1461 if (flagtmp
& SAF_ESCAPED
)
1462 KINCR(pks_inaborts
);
1465 if (state
->sa_flags
& SAF_RECVDUMP
) {
1467 ppp_dump_frame(state
, outmp
,
1471 flagtmp
&= ~SAF_ESCAPED
;
1473 /* Handle the received frame */
1475 outmp
= receive_frame(q
, outmp
, fcs16
,
1477 retmp
= sppp_mappend(retmp
, outmp
);
1486 /* If we're waiting for a new frame, then drop data. */
1487 if (flagtmp
& SAF_IFLUSH
) {
1492 * Start of new frame. Allocate a receive
1493 * buffer large enough to store a frame (after
1494 * un-escaping) of at least 1500 octets plus
1495 * the CRC. If MRU is negotiated to be more
1496 * than the default, then allocate that much.
1497 * In addition, we add an extra 32-bytes for a
1498 * fudge factor, in case the peer doesn't do
1499 * arithmetic very well.
1501 if (outmp
== NULL
) {
1504 if ((maxlen
= state
->sa_mru
) < PPP_MRU
)
1506 maxlen
+= PPP_FCS32LEN
+ 32;
1507 outmp
= allocb(maxlen
, BPRI_MED
);
1510 * If allocation fails, try again on
1511 * the next frame. (Go into discard
1514 if (outmp
== NULL
) {
1515 KINCR(pks_inallocfails
);
1516 flagtmp
|= SAF_IFLUSH
;
1521 tpmax
= outmp
->b_datap
->db_lim
;
1523 /* Neither flag can possibly be set here. */
1524 flagtmp
&= ~(SAF_IFLUSH
| SAF_ESCAPED
);
1525 fcs16
= PPPINITFCS16
;
1526 fcs32
= PPPINITFCS32
;
1530 * If the peer sends us a character that's in
1531 * our receive character map, then that's
1532 * junk. Discard it without changing state.
1533 * If they previously sent us an escape
1534 * character, then toggle this one and
1535 * continue. Otherwise, if they're now sending
1536 * escape, set the flag for next time.
1538 if (IN_RX_MAP(chr
, state
->sa_raccm
)) {
1539 KINCR(pks_inbadchars
);
1540 KOR(pks_inbadcharmask
, 1 << chr
);
1543 if (flagtmp
& SAF_ESCAPED
) {
1545 flagtmp
&= ~SAF_ESCAPED
;
1546 } else if (chr
== PPP_ESCAPE
) {
1547 flagtmp
|= SAF_ESCAPED
;
1552 * Unless the peer is confused about the
1553 * negotiated MRU, we should never get a frame
1554 * that is too long. If it happens, toss it
1555 * away and begin discarding data until we see
1556 * the end of the frame.
1559 fcs16
= PPPFCS16(fcs16
, chr
);
1560 fcs32
= PPPFCS32(fcs32
, chr
);
1563 KINCR(pks_intoolongs
);
1564 cmn_err(CE_CONT
, PPP_DRV_NAME
1565 "%d: frame too long (%d bytes)\n",
1567 (int)(tpmax
- outmp
->b_rptr
));
1572 flagtmp
|= SAF_IFLUSH
;
1577 * Free the buffer we just processed and move on to
1580 mpnext
= mp
->b_cont
;
1584 state
->sa_flags
= flagtmp
;
1585 if ((state
->sa_rx_buf
= outmp
) != NULL
)
1587 state
->sa_infcs16
= fcs16
;
1588 state
->sa_infcs32
= fcs32
;
1590 #ifdef HANDLE_ZERO_LENGTH
1591 if (nprocessed
<= 0) {
1592 outmp
= allocb(0, BPRI_MED
);
1593 if (outmp
!= NULL
) {
1594 outmp
->b_datap
->db_type
= M_HANGUP
;
1595 retmp
= sppp_mappend(retmp
, outmp
);
1603 * Nifty packet dumper; copied from AIX 4.1 port. This routine dumps
1604 * the raw received and transmitted data through syslog. This allows
1605 * debug of communications problems without resorting to a line
1608 * The expression "3*BYTES_PER_LINE" used frequently here represents
1609 * the size of each hex value printed -- two hex digits and a space.
1611 #define BYTES_PER_LINE 8
1613 ppp_dump_frame(sppp_ahdlc_t
*state
, mblk_t
*mptr
, const char *msg
)
1616 * Buffer is big enough for hex digits, two spaces, ASCII output,
1619 char buf
[3 * BYTES_PER_LINE
+ 2 + BYTES_PER_LINE
+ 1];
1620 uchar_t
*rptr
, *eptr
;
1623 static const char digits
[] = "0123456789abcdef";
1625 cmn_err(CE_CONT
, "!ppp_async%d: %s %ld bytes\n", state
->sa_unit
,
1626 msg
, msgsize(mptr
));
1629 /* Add filler spaces between hex output and ASCII */
1630 buf
[3 * BYTES_PER_LINE
] = ' ';
1631 buf
[3 * BYTES_PER_LINE
+ 1] = ' ';
1632 /* Add NUL byte at end */
1633 buf
[sizeof (buf
) - 1] = '\0';
1634 while (mptr
!= NULL
) {
1635 rptr
= mptr
->b_rptr
; /* get pointer to beginning */
1636 eptr
= mptr
->b_wptr
;
1637 while (rptr
< eptr
) {
1639 /* convert byte to ascii hex */
1640 *bp
++ = digits
[chr
>> 4];
1641 *bp
++ = digits
[chr
& 0xf];
1643 /* Insert ASCII past hex output and filler */
1644 buf
[3 * BYTES_PER_LINE
+ 2 + i
] =
1645 (chr
>= 0x20 && chr
<= 0x7E) ? (char)chr
: '.';
1647 if (i
>= BYTES_PER_LINE
) {
1648 cmn_err(CE_CONT
, "!ppp%d: %s\n", state
->sa_unit
,
1654 mptr
= mptr
->b_cont
;
1657 /* fill over unused hex display positions */
1658 while (bp
< buf
+ 3 * BYTES_PER_LINE
)
1660 /* terminate ASCII string at right position */
1661 buf
[3 * BYTES_PER_LINE
+ 2 + i
] = '\0';
1662 cmn_err(CE_CONT
, "!ppp%d: %s\n", state
->sa_unit
, buf
);
1667 spppasyn_muxencode(queue_t
*q
, mblk_t
*mp
)
1669 sppp_ahdlc_t
*state
= (sppp_ahdlc_t
*)q
->q_ptr
;
1683 proto
= MSG_BYTE(mp
, i
);
1685 if (proto
== PPP_ALLSTATIONS
) {
1688 proto
= MSG_BYTE(mp
, i
);
1692 if ((proto
& 1) == 0) {
1693 proto
= (proto
<< 8) + MSG_BYTE(mp
, i
);
1700 if (len
> PPP_MAX_MUX_LEN
|| (proto
& 0x8000)) {
1702 /* send the queued frames */
1703 if (state
->sa_mqhead
!= NULL
) {
1704 /* increment counter if it is MUX pkt */
1705 if (state
->sa_mqtail
!= NULL
)
1707 send_frame
= ahdlc_encode(q
, state
->sa_mqhead
);
1710 /* send the current frame */
1711 mp
= ahdlc_encode(q
, mp
);
1712 send_frame
= sppp_mcat(send_frame
, mp
);
1714 /* reset the state values over here */
1715 RESET_MUX_VALUES(state
);
1716 return (send_frame
);
1719 /* len + 1 , since we add the mux overhead */
1721 /* subtract the protocol length if protocol matches */
1722 if (state
->sa_proto
== proto
)
1726 if ((state
->sa_mqlen
+ nlen
) >= state
->sa_mru
) {
1728 /* send the existing queued frames */
1729 if (state
->sa_mqhead
!= NULL
) {
1730 /* increment counter if it is MUX pkt */
1731 if (state
->sa_mqtail
!= NULL
)
1733 send_frame
= ahdlc_encode(q
, state
->sa_mqhead
);
1736 /* reset state values */
1737 RESET_MUX_VALUES(state
);
1740 /* add the current frame to the queue */
1741 if (state
->sa_mqhead
!= NULL
) {
1743 if (state
->sa_mqtail
== NULL
) {
1746 * this is the first mblk in the queue create
1747 * a new frame to hold the PPP MUX header
1749 if ((new_frame
= allocb(PPP_HDRLEN
+1,
1750 BPRI_MED
)) == NULL
) {
1751 return (send_frame
);
1754 if (!IS_COMP_AC(state
)) {
1755 /* add the header */
1756 *new_frame
->b_wptr
++ = PPP_ALLSTATIONS
;
1757 *new_frame
->b_wptr
++ = PPP_UI
;
1760 /* do protocol compression */
1761 if (IS_COMP_PROT(state
)) {
1762 *new_frame
->b_wptr
++ = PPP_MUX
;
1764 *new_frame
->b_wptr
++ = 0;
1765 *new_frame
->b_wptr
++ = PPP_MUX
;
1768 *new_frame
->b_wptr
++ = PFF
|
1769 (state
->sa_mqlen
- protolen
- 1);
1771 if (DB_REF(mp
) > 1) {
1772 tmp
= copymsg(state
->sa_mqhead
);
1773 freemsg(state
->sa_mqhead
);
1774 if ((state
->sa_mqhead
= tmp
) == NULL
) {
1775 return (send_frame
);
1779 if (state
->sa_mqhead
->b_rptr
[0] == PPP_ALLSTATIONS
)
1780 state
->sa_mqhead
->b_rptr
+= 2;
1782 linkb(new_frame
, state
->sa_mqhead
);
1783 state
->sa_mqtail
= state
->sa_mqhead
;
1784 /* point mqtail to the last mblk_t */
1785 while (state
->sa_mqtail
->b_cont
!= NULL
)
1786 state
->sa_mqtail
= state
->sa_mqtail
->b_cont
;
1788 /* change state->sa_mqhead */
1789 state
->sa_mqhead
= new_frame
;
1793 if (state
->sa_proto
== proto
) {
1795 /* Check if the mblk_t is being referenced */
1796 if (DB_REF(mp
) > 1) {
1799 if ((mp
= tmp
) == NULL
) {
1800 return (send_frame
);
1805 * match,can remove the protocol field
1806 * and write data there
1808 mp
->b_rptr
+= hdrlen
;
1810 * protolen - 1 ,because the the byte with
1811 * the PFF bit and the length field have
1814 mp
->b_rptr
+= (protolen
- 1);
1815 *mp
->b_rptr
= (len
- protolen
) & 0xff;
1819 * no match, there are three options
1821 * 2. write in mqtail
1822 * 3. alloc a new blk for just one byte
1824 /* Check if the mblk_t is being referenced */
1825 if (DB_REF(mp
) > 1) {
1828 if ((mp
= tmp
) == NULL
) {
1829 return (send_frame
);
1835 mp
->b_rptr
+= (hdrlen
-1);
1836 *mp
->b_rptr
= PFF
| (len
);
1838 } else if (state
->sa_mqtail
->b_wptr
<
1839 DB_LIM(state
->sa_mqtail
)) {
1840 *state
->sa_mqtail
->b_wptr
++ = PFF
|len
;
1842 /* allocate a new mblk & add the byte */
1843 /* write the data */
1844 if ((new_frame
= allocb(1, BPRI_MED
))
1847 return (send_frame
);
1849 *new_frame
->b_wptr
++ = PFF
| (len
);
1850 linkb(state
->sa_mqtail
, new_frame
);
1854 state
->sa_proto
= proto
;
1857 linkb(state
->sa_mqtail
, mp
);
1858 state
->sa_mqtail
= mp
;
1859 while (state
->sa_mqtail
->b_cont
!= NULL
)
1860 state
->sa_mqtail
= state
->sa_mqtail
->b_cont
;
1861 state
->sa_mqlen
+= nlen
;
1864 state
->sa_mqhead
= mp
;
1865 state
->sa_mqlen
= len
+ protolen
+ 1;
1866 state
->sa_proto
= proto
;
1869 if (state
->sa_timeout_id
== 0) {
1870 state
->sa_timeout_id
= qtimeout(q
, spppasyn_timer
, q
,
1871 (drv_usectohz(state
->sa_timeout_usec
)));
1873 return (send_frame
);
1877 * Called from receive frame, this routine checks if it is a PPP_MUX
1878 * packet and demuxes it. The returned pointer is a chain of mblks
1879 * using b_next and representing the demultiplexed packets.
1882 spppasyn_inpkt(queue_t
*q
, mblk_t
*mp
)
1884 sppp_ahdlc_t
*state
= (sppp_ahdlc_t
*)q
->q_ptr
;
1886 ushort_t prev_proto
;
1887 uint32_t len
; /* length of subframe */
1893 if (!(mp
->b_rptr
[0] & PFF
)) {
1894 KINCR(pks_inmuxerrs
);
1895 (void) putnextctl1(q
, M_CTL
, PPPCTL_IERROR
);
1900 /* initialise the Last protocol and protocol length */
1904 * Taking into granted that the decoded frame is contiguous
1907 while (mp
->b_rptr
< mp
->b_wptr
) {
1910 * get the last protocol, protocol length
1911 * and the length of the message
1914 /* protocol field flag and length */
1915 muxhdr
= mp
->b_rptr
[0];
1916 len
= muxhdr
& ~PFF
;
1920 /* check if there and enough bytes left in pkt */
1921 if (MBLKL(mp
) < len
) {
1922 KINCR(pks_inmuxerrs
);
1923 (void) putnextctl1(q
, M_CTL
, PPPCTL_IERROR
);
1927 /* allocate memory for the header length */
1928 if ((hdrmp
= allocb(PPP_HDRLEN
, BPRI_MED
)) == NULL
) {
1929 KINCR(pks_inallocfails
);
1933 /* add the ppp header to the pkt */
1934 *hdrmp
->b_wptr
++ = PPP_ALLSTATIONS
;
1935 *hdrmp
->b_wptr
++ = PPP_UI
;
1937 /* check if the protocol field flag is set */
1940 /* get the protocol */
1941 proto
= MSG_BYTE(mp
, 0);
1942 if ((proto
& 1) == 0)
1943 proto
= (proto
<< 8) + MSG_BYTE(mp
, 1);
1948 if (!IS_DECOMP_PROT(state
))
1949 *hdrmp
->b_wptr
++ = prev_proto
>> 8;
1950 *hdrmp
->b_wptr
++ = (prev_proto
& 0xff);
1953 /* get the payload from the MUXed packet */
1954 subframe
= dupmsg(mp
);
1955 subframe
->b_wptr
= mp
->b_rptr
+ len
;
1957 /* link the subframe to the new frame */
1958 linkb(hdrmp
, subframe
);
1961 retmp
= sppp_mappend(retmp
, hdrmp
);
1963 /* move the read pointer beyond this subframe */
1973 * timer routine which sends out the queued pkts *
1976 spppasyn_timer(void *arg
)
1979 sppp_ahdlc_t
*state
;
1984 state
= (sppp_ahdlc_t
*)q
->q_ptr
;
1986 if (state
->sa_mqhead
!= NULL
) {
1987 /* increment counter */
1988 if (state
->sa_mqtail
!= NULL
)
1990 if ((mp
= ahdlc_encode(q
, state
->sa_mqhead
)) != NULL
)
1992 /* reset the state values over here */
1993 RESET_MUX_VALUES(state
);
1995 /* clear timeout_id */
1996 state
->sa_timeout_id
= 0;