1 /* 2 * spppasyn.c - STREAMS module for doing PPP asynchronous HDLC. 3 * 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. 7 * 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. 11 * 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 18 * 19 * Copyright (c) 1994 The Australian National University. 20 * All rights reserved. 21 * 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 27 * any purpose. 28 * 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 33 * OF SUCH DAMAGE. 34 * 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, 40 * OR MODIFICATIONS. 41 * 42 * $Id: ppp_ahdlc.c,v 1.16 2000/03/06 19:38:12 masputra Exp $ 43 */ 44 45 #pragma ident "%Z%%M% %I% %E% SMI" 46 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> 53 #include <sys/conf.h> 54 #include <sys/kmem.h> 55 #include <sys/crc32.h> 56 #include <sys/cmn_err.h> 57 #include <sys/ddi.h> 58 59 #include <net/ppp_defs.h> 60 #include <net/pppio.h> 61 62 #include "s_common.h" 63 64 #ifdef DEBUG 65 #define REPORT_CRC_TYPE 66 #endif 67 #include "spppasyn.h" 68 69 /* 70 * This is used to tag official Solaris sources. Please do not define 71 * "INTERNAL_BUILD" when building this software outside of Sun 72 * Microsystems. 73 */ 74 #ifdef INTERNAL_BUILD 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$"; 79 80 /* LINTED */ 81 static const char buildtime[] = "Built " __DATE__ " at " __TIME__ 82 #ifdef DEBUG 83 " DEBUG" 84 #endif 85 "\n"; 86 #endif /* INTERNAL_BUILD */ 87 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 *); 97 98 #define RESET_MUX_VALUES(x) { \ 99 x->sa_mqhead = x->sa_mqtail = NULL; \ 100 x->sa_proto = 0; \ 101 x->sa_mqlen = 0; \ 102 } 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) 113 114 /* 115 * Don't send HDLC start flag if last transmit is within 1.5 seconds - 116 * FLAG_TIME is defined in nanoseconds. 117 */ 118 #define FLAG_TIME 1500000000ul 119 120 /* 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. 129 */ 130 #define LCP_USE_DFLT(mp) ((code = MSG_BYTE((mp), 4)) < 9 || code > 11) 131 132 /* 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 135 * each. 136 */ 137 #define IN_TX_MAP(c, m) \ 138 ((m)[(c) >> 5] & (1 << ((c) & 0x1f))) 139 140 /* 141 * Checks the 32-bit receive ACCM to see if the byte should have been 142 * escaped by peer. 143 */ 144 #define IN_RX_MAP(c, m) (((c) < 0x20) && ((m) & (1 << (c)))) 145 146 static struct module_info spppasyn_modinfo = { 147 AHDLC_MOD_ID, /* mi_idnum */ 148 AHDLC_MOD_NAME, /* mi_idname */ 149 0, /* mi_minpsz */ 150 INFPSZ, /* mi_maxpsz */ 151 0, /* mi_hiwat */ 152 0 /* mi_lowat */ 153 }; 154 155 static struct qinit spppasyn_rinit = { 156 spppasyn_rput, /* qi_putp */ 157 NULL, /* qi_srvp */ 158 spppasyn_open, /* qi_qopen */ 159 spppasyn_close, /* qi_qclose */ 160 NULL, /* qi_qadmin */ 161 &spppasyn_modinfo, /* qi_minfo */ 162 NULL /* qi_mstat */ 163 }; 164 165 static struct qinit spppasyn_winit = { 166 spppasyn_wput, /* qi_putp */ 167 NULL, /* qi_srvp */ 168 NULL, /* qi_qopen */ 169 NULL, /* qi_qclose */ 170 NULL, /* qi_qadmin */ 171 &spppasyn_modinfo, /* qi_minfo */ 172 NULL /* qi_mstat */ 173 }; 174 175 struct streamtab spppasyn_tab = { 176 &spppasyn_rinit, /* st_rdinit */ 177 &spppasyn_winit, /* st_wrinit */ 178 NULL, /* st_muxrinit */ 179 NULL, /* st_muxwinit */ 180 }; 181 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", 192 #endif 193 }; 194 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) 201 202 static void ppp_dump_frame(sppp_ahdlc_t *state, mblk_t *mptr, 203 const char *msg); 204 205 /* 206 * RCV_B7_1, etc., defined in net/pppio.h, are stored in flags also. 207 */ 208 #define RCV_FLAGS (RCV_B7_1 | RCV_B7_0 | RCV_ODDP | RCV_EVNP) 209 210 /* 211 * FCS lookup table as calculated by genfcstab. 212 */ 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 246 }; 247 248 /* 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 254 * bit 7 set to 0.) 255 */ 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, 342 RCV_B7_1|RCV_EVNP 343 }; 344 345 /* 346 * Append two lists; preserve message boundaries. 347 * Warning: uses b_next. 348 */ 349 static mblk_t * 350 sppp_mappend(mblk_t *m1, mblk_t *m2) 351 { 352 mblk_t *mret; 353 354 if (m1 == NULL) 355 return (m2); 356 if (m2 == NULL) 357 return (m1); 358 359 mret = m1; 360 while (m1->b_next != NULL) 361 m1 = m1->b_next; 362 m1->b_next = m2; 363 return (mret); 364 } 365 366 /* 367 * Concatenate two mblk lists. 368 */ 369 static mblk_t * 370 sppp_mcat(mblk_t *m1, mblk_t *m2) 371 { 372 mblk_t *mret; 373 374 if (m1 == NULL) 375 return (m2); 376 if (m2 == NULL) 377 return (m1); 378 379 mret = m1; 380 while (m1->b_cont != NULL) 381 m1 = m1->b_cont; 382 m1->b_cont = m2; 383 return (mret); 384 } 385 386 /* 387 * spppasyn_open() 388 * 389 * STREAMS module open (entry) point. Called when spppasyn is pushed 390 * onto an asynchronous serial stream. 391 */ 392 /* ARGSUSED */ 393 static int 394 spppasyn_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp) 395 { 396 sppp_ahdlc_t *state; 397 398 ASSERT(q != NULL); 399 400 if (q->q_ptr != NULL) { 401 return (0); /* return if already opened */ 402 } 403 404 if (sflag != MODOPEN) { 405 return (EINVAL); /* only open as a module */ 406 } 407 408 state = (sppp_ahdlc_t *)kmem_zalloc(sizeof (sppp_ahdlc_t), KM_SLEEP); 409 ASSERT(state != NULL); 410 411 q->q_ptr = (caddr_t)state; 412 WR(q)->q_ptr = (caddr_t)state; 413 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 */ 417 418 qprocson(q); 419 420 return (0); 421 } 422 423 /* 424 * spppasyn_close() 425 * 426 * STREAMS module close (exit) point 427 */ 428 /* ARGSUSED */ 429 static int 430 spppasyn_close(queue_t *q, int flag, cred_t *credp) 431 { 432 sppp_ahdlc_t *state; 433 434 ASSERT(q != NULL); 435 state = (sppp_ahdlc_t *)q->q_ptr; 436 ASSERT(state != NULL); 437 438 /* We're leaving now. No more calls, please. */ 439 qprocsoff(q); 440 441 if (state->sa_rx_buf != NULL) { 442 freemsg(state->sa_rx_buf); 443 state->sa_rx_buf = NULL; 444 } 445 446 if (state->sa_ksp != NULL) { 447 kstat_delete(state->sa_ksp); 448 state->sa_ksp = NULL; 449 } 450 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); 456 457 q->q_ptr = NULL; 458 WR(q)->q_ptr = NULL; 459 kmem_free(state, sizeof (sppp_ahdlc_t)); 460 461 return (0); 462 } 463 464 /* 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. 468 */ 469 static void 470 create_kstats(sppp_ahdlc_t *state) 471 { 472 kstat_t *ksp; 473 char unitname[KSTAT_STRLEN]; 474 int nstat, i; 475 kstat_named_t *knt; 476 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++) { 480 #ifdef DEBUG 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); 484 else 485 #endif 486 (void) strncpy(knt->name, kstat_names[i], 487 sizeof (knt->name)); 488 knt->data_type = KSTAT_DATA_UINT32; 489 } 490 /* 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. 495 */ 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); 499 if (ksp != NULL) { 500 ksp->ks_data = (void *)&state->sa_kstats; 501 kstat_install(ksp); 502 } 503 state->sa_ksp = ksp; 504 #ifdef REPORT_CRC_TYPE 505 KSET(pks_outcrctype, 16); 506 KSET(pks_incrctype, 16); 507 #endif 508 } 509 510 /* 511 * spppasyn_inner_ioctl 512 * 513 * MT-Perimeters: 514 * exclusive inner 515 * 516 * Handle state-affecting ioctls. 517 */ 518 static void 519 spppasyn_inner_ioctl(queue_t *q, mblk_t *mp) 520 { 521 sppp_ahdlc_t *state; 522 struct iocblk *iop; 523 int error; 524 int flagval; 525 int len; 526 uint32_t mux_flags; 527 uint32_t mask; 528 int flagmask; 529 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); 534 535 error = EINVAL; 536 len = 0; 537 538 switch (iop->ioc_cmd) { 539 case PPPIO_XFCS: 540 /* Check for valid option length */ 541 if (iop->ioc_count != sizeof (uint32_t) || mp->b_cont == NULL) 542 break; 543 544 /* Grab flag value */ 545 flagval = *(uint32_t *)mp->b_cont->b_rptr; 546 if (flagval < PPPFCS_16 || flagval > PPPFCS_NONE) 547 break; 548 state->sa_flags &= ~SAF_XMITCRC32 & ~SAF_XMITCRCNONE; 549 if (flagval == PPPFCS_32) { 550 #ifdef REPORT_CRC_TYPE 551 KSET(pks_outcrctype, 32); 552 #endif 553 state->sa_flags |= SAF_XMITCRC32; 554 } else if (flagval == PPPFCS_NONE) { 555 #ifdef REPORT_CRC_TYPE 556 KSET(pks_outcrctype, 0); 557 #endif 558 state->sa_flags |= SAF_XMITCRCNONE; 559 } 560 #ifdef REPORT_CRC_TYPE 561 else { 562 KSET(pks_outcrctype, 16); 563 } 564 #endif 565 566 /* Return success */ 567 error = 0; 568 break; 569 570 case PPPIO_RFCS: 571 /* Check for valid option length */ 572 if (iop->ioc_count != sizeof (uint32_t) || mp->b_cont == NULL) 573 break; 574 575 /* Grab flag value */ 576 flagval = *(uint32_t *)mp->b_cont->b_rptr; 577 if (flagval < PPPFCS_16 || flagval > PPPFCS_NONE) 578 break; 579 state->sa_flags &= ~SAF_RECVCRC32 & ~SAF_RECVCRCNONE; 580 if (flagval == PPPFCS_32) { 581 #ifdef REPORT_CRC_TYPE 582 KSET(pks_incrctype, 32); 583 #endif 584 state->sa_flags |= SAF_RECVCRC32; 585 } else if (flagval == PPPFCS_NONE) { 586 #ifdef REPORT_CRC_TYPE 587 KSET(pks_incrctype, 0); 588 #endif 589 state->sa_flags |= SAF_RECVCRCNONE; 590 } 591 #ifdef REPORT_CRC_TYPE 592 else { 593 KSET(pks_incrctype, 16); 594 } 595 #endif 596 597 /* Return success */ 598 error = 0; 599 break; 600 601 case PPPIO_XACCM: 602 /* Check for valid asyncmap length */ 603 if (iop->ioc_count < sizeof (uint32_t) || 604 iop->ioc_count > sizeof (ext_accm) || 605 mp->b_cont == NULL) 606 break; 607 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); 611 612 state->sa_xaccm[2] &= ~0x40000000; /* don't escape 0x5e */ 613 state->sa_xaccm[3] |= 0x60000000; /* escape 0x7d, 0x7e */ 614 615 error = 0; 616 break; 617 618 case PPPIO_RACCM: 619 /* Check for valid asyncmap length (only ctrl chars) */ 620 if (iop->ioc_count != sizeof (uint32_t) || 621 mp->b_cont == NULL) 622 break; 623 624 state->sa_raccm = *(uint32_t *)mp->b_cont->b_rptr; 625 626 error = 0; 627 break; 628 629 case PPPIO_LASTMOD: 630 /* We already know this. */ 631 state->sa_flags |= SAF_LASTMOD; 632 error = 0; 633 break; 634 635 case PPPIO_MUX: 636 /* set the compression flags */ 637 if (iop->ioc_count != 2 * sizeof (uint32_t) || 638 mp->b_cont == NULL) 639 break; 640 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]; 644 if (mux_flags != 0) 645 state->sa_flags = (state->sa_flags & ~mask) | (mask); 646 647 /* set the multiplexing timer value */ 648 if (mask & R_MUXMASK) 649 state->sa_timeout_usec = mux_flags; 650 651 error = 0; 652 break; 653 654 case PPPIO_CFLAGS: 655 if (iop->ioc_count != 2 * sizeof (uint32_t) || 656 mp->b_cont == NULL) 657 break; 658 659 flagval = (((uint32_t *)mp->b_cont->b_rptr)[0] << 20) & 660 (SAF_RDECOMP_PROT | SAF_RDECOMP_AC | SAF_XCOMP_PROT | 661 SAF_XCOMP_AC); 662 flagmask = (((uint32_t *)mp->b_cont->b_rptr)[1] << 20) & 663 (SAF_RDECOMP_PROT | SAF_RDECOMP_AC | SAF_XCOMP_PROT | 664 SAF_XCOMP_AC); 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); 668 error = 0; 669 break; 670 671 case PPPIO_DEBUG: 672 if (iop->ioc_count != sizeof (uint32_t) || mp->b_cont == NULL) 673 break; 674 675 flagval = *(uint32_t *)mp->b_cont->b_rptr; 676 if (flagval != PPPDBG_LOG + PPPDBG_AHDLC) { 677 putnext(q, mp); 678 return; 679 } 680 cmn_err(CE_CONT, AHDLC_MOD_NAME "%d: debug log enabled\n", 681 state->sa_unit); 682 state->sa_flags |= SAF_XMITDUMP | SAF_RECVDUMP; 683 error = 0; 684 break; 685 } 686 687 if (error == 0) { 688 /* Success; tell the user */ 689 if (mp->b_cont == NULL) 690 len = 0; 691 else 692 mp->b_cont->b_wptr = mp->b_cont->b_rptr + len; 693 miocack(q, mp, len, 0); 694 } else { 695 /* Failure; send error back upstream. */ 696 KINCR(pks_ioctlserr); 697 miocnak(q, mp, 0, error); 698 } 699 } 700 701 /* 702 * spppasyn_inner_mctl 703 * 704 * MT-Perimeters: 705 * exclusive inner 706 * 707 * Handle state-affecting M_CTL messages. 708 */ 709 static void 710 spppasyn_inner_mctl(queue_t *q, mblk_t *mp) 711 { 712 sppp_ahdlc_t *state; 713 int msglen; 714 int error; 715 716 ASSERT(q != NULL && mp != NULL); 717 state = (sppp_ahdlc_t *)q->q_ptr; 718 ASSERT(state != NULL); 719 720 msglen = MBLKL(mp); 721 error = 0; 722 switch (*mp->b_rptr) { 723 case PPPCTL_MTU: 724 /* Just ignore the MTU */ 725 break; 726 727 case PPPCTL_MRU: 728 if (msglen != 4) 729 error = EINVAL; 730 else 731 state->sa_mru = 732 ((ushort_t *)mp->b_rptr)[1]; 733 break; 734 735 case PPPCTL_UNIT: 736 if (state->sa_ksp != NULL) { 737 error = EINVAL; 738 break; 739 } 740 if (msglen == 2) 741 state->sa_unit = mp->b_rptr[1]; 742 else if (msglen == 8) 743 state->sa_unit = 744 ((uint32_t *)mp->b_rptr)[1]; 745 else 746 error = EINVAL; 747 if (error == 0 && state->sa_ksp == NULL) 748 create_kstats(state); 749 break; 750 } 751 752 if (error > 0) { 753 KINCR(pks_ctlserr); 754 } 755 if (state->sa_flags & SAF_LASTMOD) { 756 freemsg(mp); 757 } else { 758 KINCR(pks_ctlsfwd); 759 putnext(q, mp); 760 } 761 } 762 763 /* 764 * spppasyn_wput() 765 * 766 * MT-Perimeters: 767 * exclusive inner. 768 * 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. 771 */ 772 static int 773 spppasyn_wput(queue_t *q, mblk_t *mp) 774 { 775 sppp_ahdlc_t *state; 776 struct iocblk *iop; 777 int error; 778 mblk_t *np; 779 struct ppp_stats64 *psp; 780 int msglen; 781 782 ASSERT(q != NULL && mp != NULL); 783 state = (sppp_ahdlc_t *)q->q_ptr; 784 ASSERT(state != NULL); 785 786 switch (MTYPE(mp)) { 787 788 case M_DATA: 789 /* 790 * A data packet - do character-stuffing and FCS, and 791 * send it onwards. The blocks are freed as we go. 792 */ 793 if (IS_XMUX_ENABLED(state)) 794 mp = spppasyn_muxencode(q, mp); 795 else 796 mp = ahdlc_encode(q, mp); 797 if (mp != NULL) 798 putnext(q, mp); 799 break; 800 801 case M_IOCTL: 802 803 KINCR(pks_ioctls); 804 iop = (struct iocblk *)mp->b_rptr; 805 806 msglen = 0; 807 808 switch (iop->ioc_cmd) { 809 case PPPIO_XFCS: 810 case PPPIO_RFCS: 811 case PPPIO_XACCM: 812 case PPPIO_RACCM: 813 case PPPIO_LASTMOD: 814 case PPPIO_DEBUG: 815 case PPPIO_MUX: 816 case PPPIO_CFLAGS: 817 spppasyn_inner_ioctl(q, mp); 818 return (0); 819 820 case PPPIO_GCLEAN: 821 np = allocb(sizeof (uint32_t), BPRI_HI); 822 if (np == NULL) { 823 error = ENOSR; 824 break; 825 } 826 if (mp->b_cont != NULL) { 827 freemsg(mp->b_cont); 828 } 829 mp->b_cont = np; 830 831 *(uint32_t *)np->b_wptr = state->sa_flags & RCV_FLAGS; 832 833 msglen = sizeof (uint32_t); 834 np->b_wptr += msglen; 835 error = 0; 836 break; 837 838 case PPPIO_GETSTAT: 839 error = EINVAL; 840 break; 841 842 case PPPIO_GETSTAT64: 843 np = allocb(sizeof (*psp), BPRI_HI); 844 if (np == NULL) { 845 error = ENOSR; 846 break; 847 } 848 if (mp->b_cont != NULL) { 849 freemsg(mp->b_cont); 850 } 851 mp->b_cont = np; 852 853 psp = (struct ppp_stats64 *)np->b_wptr; 854 bzero((caddr_t)psp, sizeof (*psp)); 855 psp->p = state->sa_stats; 856 857 msglen = sizeof (*psp); 858 np->b_wptr += msglen; 859 error = 0; 860 break; 861 862 case PPPIO_GTYPE: 863 np = allocb(sizeof (uint32_t), BPRI_HI); 864 if (np == NULL) { 865 error = ENOSR; 866 break; 867 } 868 if (mp->b_cont != NULL) { 869 freemsg(mp->b_cont); 870 } 871 mp->b_cont = np; 872 873 *(uint32_t *)np->b_wptr = PPPTYP_AHDLC; 874 875 msglen = sizeof (uint32_t); 876 np->b_wptr += msglen; 877 error = 0; 878 break; 879 880 default: 881 /* Unknown ioctl -- forward along */ 882 KINCR(pks_ioctlsfwd); 883 putnext(q, mp); 884 return (0); 885 } 886 887 if (error == 0) { 888 /* Success; tell the user */ 889 miocack(q, mp, msglen, 0); 890 } else { 891 /* Failure; send error back upstream. */ 892 KINCR(pks_ioctlserr); 893 miocnak(q, mp, 0, error); 894 } 895 896 break; 897 898 case M_CTL: 899 KINCR(pks_ctls); 900 spppasyn_inner_mctl(q, mp); 901 break; 902 903 default: 904 if (state->sa_flags & (SAF_XMITDUMP|SAF_RECVDUMP)) 905 cmn_err(CE_CONT, 906 "spppasyn_wpur: unknown buffer type %d", 907 MTYPE(mp)); 908 KINCR(pks_unknownwrs); 909 putnext(q, mp); 910 break; 911 } 912 913 return (0); 914 } 915 916 /* 917 * spppasyn_rput() 918 * 919 * MT-Perimeters: 920 * exclusive inner. 921 * 922 * Read side put routine. This is called by the async serial driver 923 * below us to handle received data and returned signals (like 924 * hang-up). 925 */ 926 static int 927 spppasyn_rput(queue_t *q, mblk_t *mp) 928 { 929 sppp_ahdlc_t *state; 930 mblk_t *mpnext; 931 932 ASSERT(q != NULL && mp != NULL); 933 state = (sppp_ahdlc_t *)q->q_ptr; 934 ASSERT(state != NULL); 935 936 switch (MTYPE(mp)) { 937 938 case M_DATA: 939 /* Note -- decoder frees the buffers */ 940 mp = ahdlc_decode(q, mp); 941 while (mp != NULL) { 942 mpnext = mp->b_next; 943 mp->b_next = NULL; 944 putnext(q, mp); 945 mp = mpnext; 946 } 947 break; 948 949 case M_HANGUP: 950 KINCR(pks_hangups); 951 state->sa_flags |= SAF_IFLUSH; 952 putnext(q, mp); 953 break; 954 955 default: 956 if (state->sa_flags & (SAF_XMITDUMP|SAF_RECVDUMP)) { 957 if (MTYPE(mp) == M_IOCTL) 958 cmn_err(CE_CONT, 959 "spppasyn_rput: unexpected ioctl %X", 960 ((struct iocblk *)mp->b_rptr)->ioc_cmd); 961 else 962 cmn_err(CE_CONT, 963 "spppasyn_rput: unknown buffer type %d", 964 MTYPE(mp)); 965 } 966 KINCR(pks_unknownrds); 967 putnext(q, mp); 968 break; 969 } 970 971 return (0); 972 } 973 974 /* 975 * ahdlc_encode 976 * 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. 980 * 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 986 * decisions. 987 */ 988 static mblk_t * 989 ahdlc_encode(queue_t *q, mblk_t *mp) 990 { 991 sppp_ahdlc_t *state; 992 uint32_t loc_xaccm[8]; 993 ushort_t fcs16; 994 uint32_t fcs32; 995 size_t msglen; 996 size_t outmp_len; 997 mblk_t *outmp; 998 mblk_t *curout; 999 mblk_t *tmp; 1000 uchar_t *ep; 1001 uchar_t *dp; 1002 uchar_t *tp; 1003 uchar_t *tpmax; 1004 #if defined(lint) || defined(_lint) 1005 uchar_t chr; /* lint likes this */ 1006 #else 1007 int chr; /* not uchar_t; more efficient this way */ 1008 /* with WorkShop compiler */ 1009 #endif 1010 int is_lcp, is_ctrl; 1011 int code; 1012 hrtime_t hrtime; 1013 uint32_t flags; /* sampled copy of flags */ 1014 1015 state = (sppp_ahdlc_t *)q->q_ptr; 1016 1017 /* Don't transmit anything obviously silly. */ 1018 msglen = msgsize(mp); 1019 if (msglen < 4) { 1020 KINCR(pks_outrunts); 1021 freemsg(mp); 1022 (void) putnextctl1(RD(q), M_CTL, PPPCTL_OERROR); 1023 return (NULL); 1024 } 1025 1026 /* 1027 * Allocate an output buffer just large enough for most cases. 1028 * Based on original work in the ppp-2.2 AIX PPP driver, we 1029 * estimate the output size as 1.25 * input message length 1030 * plus 16. If this turns out to be too small, then we'll 1031 * allocate exactly one additional buffer with two times the 1032 * remaining input length (the maximum that could possibly be 1033 * required). 1034 */ 1035 outmp_len = msglen + (msglen >> 2) + 16; 1036 outmp = allocb(outmp_len, BPRI_MED); 1037 if (outmp == NULL) 1038 goto outallocfail; 1039 1040 tp = outmp->b_wptr; 1041 1042 /* 1043 * Check if our last transmit happened within FLAG_TIME, using 1044 * the system's hrtime. 1045 */ 1046 hrtime = gethrtime(); 1047 if (ABS(hrtime - state->sa_hrtime) > FLAG_TIME) { 1048 *tp++ = PPP_FLAG; 1049 } 1050 state->sa_hrtime = hrtime; 1051 bcopy((caddr_t)state->sa_xaccm, (caddr_t)loc_xaccm, sizeof (loc_xaccm)); 1052 flags = state->sa_flags; 1053 1054 /* 1055 * LCP messages must be sent using the default escaping 1056 * (ACCM). We bend this rule a little to allow LCP 1057 * Echo-Request through with the negotiated escaping so that 1058 * we can detect bad negotiated ACCM values. If the ACCM is 1059 * bad, echos will fail and take down the link. 1060 */ 1061 is_lcp = is_ctrl = 0; 1062 code = MSG_BYTE(mp, 0); 1063 if (code == PPP_ALLSTATIONS) { 1064 if (MSG_BYTE(mp, 1) == PPP_UI) { 1065 code = MSG_BYTE(mp, 2); 1066 if (code == (PPP_LCP >> 8) && 1067 MSG_BYTE(mp, 3) == (PPP_LCP & 0xFF)) { 1068 if (LCP_USE_DFLT(mp)) 1069 is_lcp = 2; 1070 else 1071 is_lcp = 1; /* Echo-Request */ 1072 } else if (!(code & 1) && code > 0x3F) 1073 is_ctrl = 1; 1074 } 1075 } else if (!(code & 1) && code > 0x3F) 1076 is_ctrl = 1; 1077 1078 /* 1079 * If it's LCP and not just an LCP Echo-Request, then we need 1080 * to drop back to default escaping rules temporarily. 1081 */ 1082 if (is_lcp > 1) { 1083 /* 1084 * force escape on 0x00 through 0x1f 1085 * and, for RFC 1662 (and ISO 3309:1991), 0x80-0x9f. 1086 */ 1087 loc_xaccm[0] = 0xffffffff; 1088 loc_xaccm[4] = 0xffffffff; 1089 } 1090 1091 fcs16 = PPPINITFCS16; /* Initial FCS is 0xffff */ 1092 fcs32 = PPPINITFCS32; 1093 1094 /* 1095 * Process this block and the rest (if any) attached to this 1096 * one. Note that we quite intentionally ignore the type of 1097 * the buffer. The caller has checked that the first buffer 1098 * is M_DATA; all others must be so, and any that are not are 1099 * harmless driver errors. 1100 */ 1101 curout = outmp; 1102 tpmax = outmp->b_datap->db_lim; 1103 do { 1104 dp = mp->b_rptr; 1105 while (dp < (ep = mp->b_wptr)) { 1106 /* 1107 * Calculate maximum safe run length for inner loop, 1108 * regardless of escaping. 1109 */ 1110 outmp_len = (tpmax - tp) / 2; 1111 if (dp + outmp_len < ep) 1112 ep = dp + outmp_len; 1113 1114 /* 1115 * Select out on CRC type here to make the 1116 * inner byte loop more efficient. (We could 1117 * do both CRCs at all times if we wanted, but 1118 * that ends up taking an extra 8 cycles per 1119 * byte -- 47% overhead!) 1120 */ 1121 if (flags & SAF_XMITCRC32) { 1122 while (dp < ep) { 1123 chr = *dp++; 1124 fcs32 = PPPFCS32(fcs32, chr); 1125 if (IN_TX_MAP(chr, loc_xaccm)) { 1126 *tp++ = PPP_ESCAPE; 1127 chr ^= PPP_TRANS; 1128 } 1129 *tp++ = chr; 1130 } 1131 } else { 1132 while (dp < ep) { 1133 chr = *dp++; 1134 fcs16 = PPPFCS16(fcs16, chr); 1135 if (IN_TX_MAP(chr, loc_xaccm)) { 1136 *tp++ = PPP_ESCAPE; 1137 chr ^= PPP_TRANS; 1138 } 1139 *tp++ = chr; 1140 } 1141 } 1142 1143 /* 1144 * If we limited our run length and we're now low 1145 * on output space, then allocate a new output buffer. 1146 * This should rarely happen, unless the output data 1147 * has a lot of escapes. 1148 */ 1149 if (ep != mp->b_wptr && tpmax - tp < 5) { 1150 KINCR(pks_extrabufs); 1151 /* Get remaining message length */ 1152 outmp_len = (mp->b_wptr - dp) + 1153 msgsize(mp->b_cont); 1154 /* Calculate maximum required space */ 1155 outmp_len = (outmp_len + PPP_FCS32LEN) * 2 + 1; 1156 curout = allocb(outmp_len, BPRI_MED); 1157 if ((outmp->b_cont = curout) == NULL) 1158 goto outallocfail; 1159 outmp->b_wptr = tp; 1160 tp = curout->b_wptr; 1161 tpmax = curout->b_datap->db_lim; 1162 } 1163 } 1164 tmp = mp->b_cont; 1165 freeb(mp); 1166 mp = tmp; 1167 } while (mp != NULL); 1168 1169 /* 1170 * Make sure we have enough remaining room to add the CRC (if 1171 * any) and a trailing flag byte. 1172 */ 1173 outmp_len = PPP_FCS32LEN * 2 + 1; 1174 if (tpmax - tp < outmp_len) { 1175 KINCR(pks_extrabufs); 1176 curout = allocb(outmp_len, BPRI_MED); 1177 if ((outmp->b_cont = curout) == NULL) 1178 goto outallocfail; 1179 outmp->b_wptr = tp; 1180 tp = curout->b_wptr; 1181 tpmax = curout->b_datap->db_lim; 1182 } 1183 1184 /* 1185 * Network layer data is the only thing that can be sent with 1186 * no CRC at all. 1187 */ 1188 if ((flags & SAF_XMITCRCNONE) && !is_lcp && !is_ctrl) 1189 goto nocrc; 1190 1191 if (!(flags & SAF_XMITCRC32)) 1192 fcs32 = fcs16; 1193 1194 /* 1195 * Append the HDLC FCS, making sure that escaping is done on any 1196 * necessary bytes. Note that the FCS bytes are in little-endian. 1197 */ 1198 fcs32 = ~fcs32; 1199 chr = fcs32 & 0xff; 1200 if (IN_TX_MAP(chr, loc_xaccm)) { 1201 *tp++ = PPP_ESCAPE; 1202 chr ^= PPP_TRANS; 1203 } 1204 *tp++ = chr; 1205 1206 chr = (fcs32 >> 8) & 0xff; 1207 if (IN_TX_MAP(chr, loc_xaccm)) { 1208 *tp++ = PPP_ESCAPE; 1209 chr ^= PPP_TRANS; 1210 } 1211 *tp++ = chr; 1212 1213 if (flags & SAF_XMITCRC32) { 1214 chr = (fcs32 >> 16) & 0xff; 1215 if (IN_TX_MAP(chr, loc_xaccm)) { 1216 *tp++ = PPP_ESCAPE; 1217 chr ^= PPP_TRANS; 1218 } 1219 *tp++ = chr; 1220 1221 chr = (fcs32 >> 24) & 0xff; 1222 if (IN_TX_MAP(chr, loc_xaccm)) { 1223 *tp++ = PPP_ESCAPE; 1224 chr ^= PPP_TRANS; 1225 } 1226 *tp++ = chr; 1227 } 1228 1229 nocrc: 1230 /* 1231 * And finally append the HDLC flag, and send it away 1232 */ 1233 *tp++ = PPP_FLAG; 1234 ASSERT(tp < tpmax); 1235 curout->b_wptr = tp; 1236 1237 state->sa_stats.ppp_obytes += msgsize(outmp); 1238 state->sa_stats.ppp_opackets++; 1239 1240 if (state->sa_flags & SAF_XMITDUMP) 1241 ppp_dump_frame(state, outmp, "sent"); 1242 1243 KINCR(pks_dataout); 1244 return (outmp); 1245 1246 outallocfail: 1247 KINCR(pks_outallocfails); 1248 state->sa_stats.ppp_oerrors++; 1249 freemsg(outmp); 1250 freemsg(mp); 1251 (void) putnextctl1(RD(q), M_CTL, PPPCTL_OERROR); 1252 return (NULL); 1253 } 1254 1255 /* 1256 * Handle end-of-frame excitement. This is here mostly because the Solaris 1257 * C style rules require tab for indent and prohibit excessive indenting. 1258 */ 1259 static mblk_t * 1260 receive_frame(queue_t *q, mblk_t *outmp, ushort_t fcs16, uint32_t fcs32) 1261 { 1262 sppp_ahdlc_t *state = (sppp_ahdlc_t *)q->q_ptr; 1263 uchar_t *cp, *ep; 1264 int is_lcp, is_ctrl, crclen; 1265 ushort_t proto; 1266 int i; 1267 1268 cp = outmp->b_rptr; 1269 if (cp[0] == PPP_ALLSTATIONS && cp[1] == PPP_UI) 1270 cp += 2; 1271 proto = *cp++; 1272 if ((proto & 1) == 0) 1273 proto = (proto << 8) + *cp++; 1274 is_lcp = (proto == PPP_LCP); 1275 is_ctrl = (proto >= 0x4000); 1276 1277 /* 1278 * To allow for renegotiation, LCP accepts good CRCs of either 1279 * type at any time. Other control (non-network) packets must 1280 * have either CRC-16 or CRC-32, as negotiated. Network layer 1281 * packets may additionally omit the CRC entirely, if that was 1282 * negotiated. 1283 */ 1284 if ((is_lcp && (fcs16 == PPPGOODFCS16 || fcs32 == PPPGOODFCS32)) || 1285 ((fcs16 == PPPGOODFCS16 && !(state->sa_flags & SAF_RECVCRC32)) || 1286 (fcs32 == PPPGOODFCS32 && 1287 (state->sa_flags & SAF_RECVCRC32))) || 1288 (!is_ctrl && !is_lcp && (state->sa_flags & SAF_RECVCRCNONE))) { 1289 1290 state->sa_stats.ppp_ipackets++; 1291 if (is_lcp) { 1292 crclen = (fcs16 == PPPGOODFCS16) ? 1293 PPP_FCSLEN : PPP_FCS32LEN; 1294 } else { 1295 crclen = (state->sa_flags & SAF_RECVCRC32) ? 1296 PPP_FCS32LEN : PPP_FCSLEN; 1297 if (!is_ctrl && (state->sa_flags & SAF_RECVCRCNONE)) 1298 crclen = 0; 1299 } 1300 if (crclen != 0) { 1301 i = adjmsg(outmp, -crclen); 1302 ASSERT(i != 0); 1303 #if defined(lint) || defined(_lint) 1304 /* lint is happier this way in a non-DEBUG build */ 1305 i = i; 1306 #endif 1307 } 1308 1309 if (proto == PPP_MUX) { 1310 /* spppasyn_inpkt checks for PPP_MUX packets */ 1311 KINCR(pks_recvmux); 1312 /* Remove headers */ 1313 outmp->b_rptr = cp; 1314 return (spppasyn_inpkt(q, outmp)); 1315 } 1316 1317 /* 1318 * Sniff the received data stream. If we see an LCP 1319 * Configure-Ack, then pick out the ACCM setting, if 1320 * any, and configure now. This allows us to stay in 1321 * sync in case the peer is already out of Establish 1322 * phase. 1323 */ 1324 if (is_lcp && *cp == 2) { 1325 ep = outmp->b_wptr; 1326 i = (cp[2] << 8) | cp[3]; 1327 if (i > ep - cp) 1328 ep = cp; /* Discard junk */ 1329 else if (i < ep - cp) 1330 ep = cp + i; 1331 cp += 4; 1332 while (cp + 2 < ep) { 1333 if ((i = cp[1]) < 2) 1334 i = 2; 1335 if (cp + i > ep) 1336 i = ep - cp; 1337 if (cp[0] == 2 && i >= 6) { 1338 state->sa_raccm = (cp[2] << 24) | 1339 (cp[3] << 16) | (cp[4] << 8) | 1340 cp[5]; 1341 break; 1342 } 1343 cp += i; 1344 } 1345 } 1346 return (outmp); 1347 } else { 1348 KINCR(pks_incrcerrs); 1349 cmn_err(CE_CONT, PPP_DRV_NAME "%d: bad fcs (len=%ld)\n", 1350 state->sa_unit, msgsize(outmp)); 1351 1352 if (state->sa_flags & SAF_RECVDUMP) 1353 ppp_dump_frame(state, outmp, "bad data"); 1354 1355 freemsg(outmp); 1356 1357 state->sa_stats.ppp_ierrors++; 1358 1359 (void) putnextctl1(q, M_CTL, PPPCTL_IERROR); 1360 return (NULL); 1361 } 1362 } 1363 1364 /* 1365 * ahdlc_decode() 1366 * 1367 * Process received characters. 1368 * 1369 * This is handled as exclusive inner so that we don't get confused 1370 * about the state. Returns a list of packets linked by b_next. 1371 */ 1372 static mblk_t * 1373 ahdlc_decode(queue_t *q, mblk_t *mp) 1374 { 1375 sppp_ahdlc_t *state; 1376 mblk_t *retmp; /* list of packets to return */ 1377 mblk_t *outmp; /* buffer for decoded data */ 1378 mblk_t *mpnext; /* temporary ptr for unlinking */ 1379 uchar_t *dp; /* pointer to input data */ 1380 uchar_t *dpend; /* end of input data */ 1381 uchar_t *tp; /* pointer to decoded output data */ 1382 uchar_t *tpmax; /* output buffer limit */ 1383 int flagtmp; /* temporary cache of flags */ 1384 #if defined(lint) || defined(_lint) 1385 uchar_t chr; /* lint likes this */ 1386 #else 1387 int chr; /* not uchar_t; more efficient this way */ 1388 /* with WorkShop compiler */ 1389 #endif 1390 ushort_t fcs16; /* running CRC-16 */ 1391 uint32_t fcs32; /* running CRC-32 */ 1392 #ifdef HANDLE_ZERO_LENGTH 1393 size_t nprocessed; 1394 #endif 1395 1396 state = (sppp_ahdlc_t *)q->q_ptr; 1397 1398 KINCR(pks_datain); 1399 1400 state->sa_stats.ppp_ibytes += msgsize(mp); 1401 1402 if (state->sa_flags & SAF_RECVDUMP) 1403 ppp_dump_frame(state, mp, "rcvd"); 1404 1405 flagtmp = state->sa_flags; 1406 fcs16 = state->sa_infcs16; 1407 fcs32 = state->sa_infcs32; 1408 outmp = state->sa_rx_buf; 1409 if (outmp == NULL) { 1410 tp = tpmax = NULL; 1411 } else { 1412 tp = outmp->b_wptr; 1413 tpmax = outmp->b_datap->db_lim; 1414 } 1415 #ifdef HANDLE_ZERO_LENGTH 1416 nprocessed = 0; 1417 #endif 1418 1419 /* 1420 * Main input processing loop. Loop over received buffers and 1421 * each byte in each buffer. Note that we quite intentionally 1422 * ignore the type of the buffer. The caller has checked that 1423 * the first buffer is M_DATA; all others must be so, and any 1424 * that are not are harmless driver errors. 1425 */ 1426 retmp = NULL; 1427 while (mp != NULL) { 1428 1429 /* Innermost loop -- examine bytes in buffer. */ 1430 dpend = mp->b_wptr; 1431 dp = mp->b_rptr; 1432 #ifdef HANDLE_ZERO_LENGTH 1433 nprocessed += dpend - dp; 1434 #endif 1435 for (; dp < dpend; dp++) { 1436 chr = *dp; 1437 1438 /* 1439 * This should detect the lack of an 8-bit 1440 * communication channel, which is necessary 1441 * for PPP to work. 1442 */ 1443 flagtmp |= charflags[chr]; 1444 1445 /* 1446 * So we have a HDLC flag ... 1447 */ 1448 if (chr == PPP_FLAG) { 1449 1450 /* 1451 * If there's no received buffer, then 1452 * just ignore this frame marker. 1453 */ 1454 if ((flagtmp & SAF_IFLUSH) || outmp == NULL) { 1455 flagtmp &= ~SAF_IFLUSH & ~SAF_ESCAPED; 1456 continue; 1457 } 1458 1459 /* 1460 * Per RFC 1662 -- silently discard 1461 * runt frames (fewer than 4 octets 1462 * with 16 bit CRC) and frames that 1463 * end in 7D 7E (abort sequence). 1464 * These are not counted as errors. 1465 * 1466 * (We could just reset the pointers 1467 * and reuse the buffer, but this is a 1468 * rarely used error path and not 1469 * worth the optimization.) 1470 */ 1471 if ((flagtmp & SAF_ESCAPED) || 1472 tp - outmp->b_rptr < 2 + PPP_FCSLEN) { 1473 if (flagtmp & SAF_ESCAPED) 1474 KINCR(pks_inaborts); 1475 else 1476 KINCR(pks_inrunts); 1477 if (state->sa_flags & SAF_RECVDUMP) { 1478 outmp->b_wptr = tp; 1479 ppp_dump_frame(state, outmp, 1480 "runt"); 1481 } 1482 freemsg(outmp); 1483 flagtmp &= ~SAF_ESCAPED; 1484 } else { 1485 /* Handle the received frame */ 1486 outmp->b_wptr = tp; 1487 outmp = receive_frame(q, outmp, fcs16, 1488 fcs32); 1489 retmp = sppp_mappend(retmp, outmp); 1490 } 1491 1492 outmp = NULL; 1493 tp = tpmax = NULL; 1494 1495 continue; 1496 } 1497 1498 /* If we're waiting for a new frame, then drop data. */ 1499 if (flagtmp & SAF_IFLUSH) { 1500 continue; 1501 } 1502 1503 /* 1504 * Start of new frame. Allocate a receive 1505 * buffer large enough to store a frame (after 1506 * un-escaping) of at least 1500 octets plus 1507 * the CRC. If MRU is negotiated to be more 1508 * than the default, then allocate that much. 1509 * In addition, we add an extra 32-bytes for a 1510 * fudge factor, in case the peer doesn't do 1511 * arithmetic very well. 1512 */ 1513 if (outmp == NULL) { 1514 int maxlen; 1515 1516 if ((maxlen = state->sa_mru) < PPP_MRU) 1517 maxlen = PPP_MRU; 1518 maxlen += PPP_FCS32LEN + 32; 1519 outmp = allocb(maxlen, BPRI_MED); 1520 1521 /* 1522 * If allocation fails, try again on 1523 * the next frame. (Go into discard 1524 * mode.) 1525 */ 1526 if (outmp == NULL) { 1527 KINCR(pks_inallocfails); 1528 flagtmp |= SAF_IFLUSH; 1529 continue; 1530 } 1531 1532 tp = outmp->b_wptr; 1533 tpmax = outmp->b_datap->db_lim; 1534 1535 /* Neither flag can possibly be set here. */ 1536 flagtmp &= ~(SAF_IFLUSH | SAF_ESCAPED); 1537 fcs16 = PPPINITFCS16; 1538 fcs32 = PPPINITFCS32; 1539 } 1540 1541 /* 1542 * If the peer sends us a character that's in 1543 * our receive character map, then that's 1544 * junk. Discard it without changing state. 1545 * If they previously sent us an escape 1546 * character, then toggle this one and 1547 * continue. Otherwise, if they're now sending 1548 * escape, set the flag for next time. 1549 */ 1550 if (IN_RX_MAP(chr, state->sa_raccm)) { 1551 KINCR(pks_inbadchars); 1552 KOR(pks_inbadcharmask, 1 << chr); 1553 continue; 1554 } 1555 if (flagtmp & SAF_ESCAPED) { 1556 chr ^= PPP_TRANS; 1557 flagtmp &= ~SAF_ESCAPED; 1558 } else if (chr == PPP_ESCAPE) { 1559 flagtmp |= SAF_ESCAPED; 1560 continue; 1561 } 1562 1563 /* 1564 * Unless the peer is confused about the 1565 * negotiated MRU, we should never get a frame 1566 * that is too long. If it happens, toss it 1567 * away and begin discarding data until we see 1568 * the end of the frame. 1569 */ 1570 if (tp < tpmax) { 1571 fcs16 = PPPFCS16(fcs16, chr); 1572 fcs32 = PPPFCS32(fcs32, chr); 1573 *tp++ = chr; 1574 } else { 1575 KINCR(pks_intoolongs); 1576 cmn_err(CE_CONT, PPP_DRV_NAME 1577 "%d: frame too long (%d bytes)\n", 1578 state->sa_unit, 1579 (int)(tpmax - outmp->b_rptr)); 1580 1581 freemsg(outmp); 1582 outmp = NULL; 1583 tp = tpmax = NULL; 1584 flagtmp |= SAF_IFLUSH; 1585 } 1586 } 1587 1588 /* 1589 * Free the buffer we just processed and move on to 1590 * the next one. 1591 */ 1592 mpnext = mp->b_cont; 1593 freeb(mp); 1594 mp = mpnext; 1595 } 1596 state->sa_flags = flagtmp; 1597 if ((state->sa_rx_buf = outmp) != NULL) 1598 outmp->b_wptr = tp; 1599 state->sa_infcs16 = fcs16; 1600 state->sa_infcs32 = fcs32; 1601 1602 #ifdef HANDLE_ZERO_LENGTH 1603 if (nprocessed <= 0) { 1604 outmp = allocb(0, BPRI_MED); 1605 if (outmp != NULL) { 1606 outmp->b_datap->db_type = M_HANGUP; 1607 retmp = sppp_mappend(retmp, outmp); 1608 } 1609 } 1610 #endif 1611 return (retmp); 1612 } 1613 1614 /* 1615 * Nifty packet dumper; copied from AIX 4.1 port. This routine dumps 1616 * the raw received and transmitted data through syslog. This allows 1617 * debug of communications problems without resorting to a line 1618 * analyzer. 1619 * 1620 * The expression "3*BYTES_PER_LINE" used frequently here represents 1621 * the size of each hex value printed -- two hex digits and a space. 1622 */ 1623 #define BYTES_PER_LINE 8 1624 static void 1625 ppp_dump_frame(sppp_ahdlc_t *state, mblk_t *mptr, const char *msg) 1626 { 1627 /* 1628 * Buffer is big enough for hex digits, two spaces, ASCII output, 1629 * and one NUL byte. 1630 */ 1631 char buf[3 * BYTES_PER_LINE + 2 + BYTES_PER_LINE + 1]; 1632 uchar_t *rptr, *eptr; 1633 int i, chr; 1634 char *bp; 1635 static const char digits[] = "0123456789abcdef"; 1636 1637 cmn_err(CE_CONT, "!ppp_async%d: %s %ld bytes\n", state->sa_unit, 1638 msg, msgsize(mptr)); 1639 i = 0; 1640 bp = buf; 1641 /* Add filler spaces between hex output and ASCII */ 1642 buf[3 * BYTES_PER_LINE] = ' '; 1643 buf[3 * BYTES_PER_LINE + 1] = ' '; 1644 /* Add NUL byte at end */ 1645 buf[sizeof (buf) - 1] = '\0'; 1646 while (mptr != NULL) { 1647 rptr = mptr->b_rptr; /* get pointer to beginning */ 1648 eptr = mptr->b_wptr; 1649 while (rptr < eptr) { 1650 chr = *rptr++; 1651 /* convert byte to ascii hex */ 1652 *bp++ = digits[chr >> 4]; 1653 *bp++ = digits[chr & 0xf]; 1654 *bp++ = ' '; 1655 /* Insert ASCII past hex output and filler */ 1656 buf[3 * BYTES_PER_LINE + 2 + i] = 1657 (chr >= 0x20 && chr <= 0x7E) ? (char)chr : '.'; 1658 i++; 1659 if (i >= BYTES_PER_LINE) { 1660 cmn_err(CE_CONT, "!ppp%d: %s\n", state->sa_unit, 1661 buf); 1662 bp = buf; 1663 i = 0; 1664 } 1665 } 1666 mptr = mptr->b_cont; 1667 } 1668 if (bp > buf) { 1669 /* fill over unused hex display positions */ 1670 while (bp < buf + 3 * BYTES_PER_LINE) 1671 *bp++ = ' '; 1672 /* terminate ASCII string at right position */ 1673 buf[3 * BYTES_PER_LINE + 2 + i] = '\0'; 1674 cmn_err(CE_CONT, "!ppp%d: %s\n", state->sa_unit, buf); 1675 } 1676 } 1677 1678 static mblk_t * 1679 spppasyn_muxencode(queue_t *q, mblk_t *mp) 1680 { 1681 sppp_ahdlc_t *state = (sppp_ahdlc_t *)q->q_ptr; 1682 uint32_t len; 1683 uint32_t nlen; 1684 ushort_t protolen; 1685 uint32_t hdrlen; 1686 ushort_t proto; 1687 mblk_t *new_frame; 1688 mblk_t *tmp; 1689 mblk_t *send_frame; 1690 ushort_t i; 1691 1692 len = msgdsize(mp); 1693 i = 0; 1694 protolen = 1; 1695 proto = MSG_BYTE(mp, i); 1696 1697 if (proto == PPP_ALLSTATIONS) { 1698 len -= 2; 1699 i += 2; 1700 proto = MSG_BYTE(mp, i); 1701 } 1702 1703 ++i; 1704 if ((proto & 1) == 0) { 1705 proto = (proto << 8) + MSG_BYTE(mp, i); 1706 protolen++; 1707 } 1708 1709 hdrlen = i - 1; 1710 1711 send_frame = NULL; 1712 if (len > PPP_MAX_MUX_LEN || (proto & 0x8000)) { 1713 1714 /* send the queued frames */ 1715 if (state->sa_mqhead != NULL) { 1716 /* increment counter if it is MUX pkt */ 1717 if (state->sa_mqtail != NULL) 1718 KINCR(pks_sentmux); 1719 send_frame = ahdlc_encode(q, state->sa_mqhead); 1720 } 1721 1722 /* send the current frame */ 1723 mp = ahdlc_encode(q, mp); 1724 send_frame = sppp_mcat(send_frame, mp); 1725 1726 /* reset the state values over here */ 1727 RESET_MUX_VALUES(state); 1728 return (send_frame); 1729 } 1730 1731 /* len + 1 , since we add the mux overhead */ 1732 nlen = len + 1; 1733 /* subtract the protocol length if protocol matches */ 1734 if (state->sa_proto == proto) 1735 nlen -= protolen; 1736 1737 send_frame = NULL; 1738 if ((state->sa_mqlen + nlen) >= state->sa_mru) { 1739 1740 /* send the existing queued frames */ 1741 if (state->sa_mqhead != NULL) { 1742 /* increment counter if it is MUX pkt */ 1743 if (state->sa_mqtail != NULL) 1744 KINCR(pks_sentmux); 1745 send_frame = ahdlc_encode(q, state->sa_mqhead); 1746 } 1747 1748 /* reset state values */ 1749 RESET_MUX_VALUES(state); 1750 } 1751 1752 /* add the current frame to the queue */ 1753 if (state->sa_mqhead != NULL) { 1754 1755 if (state->sa_mqtail == NULL) { 1756 1757 /* 1758 * this is the first mblk in the queue create 1759 * a new frame to hold the PPP MUX header 1760 */ 1761 if ((new_frame = allocb(PPP_HDRLEN+1, 1762 BPRI_MED)) == NULL) { 1763 return (send_frame); 1764 } 1765 1766 if (!IS_COMP_AC(state)) { 1767 /* add the header */ 1768 *new_frame->b_wptr++ = PPP_ALLSTATIONS; 1769 *new_frame->b_wptr++ = PPP_UI; 1770 } 1771 1772 /* do protocol compression */ 1773 if (IS_COMP_PROT(state)) { 1774 *new_frame->b_wptr++ = PPP_MUX; 1775 } else { 1776 *new_frame->b_wptr++ = 0; 1777 *new_frame->b_wptr++ = PPP_MUX; 1778 } 1779 1780 *new_frame->b_wptr++ = PFF | 1781 (state->sa_mqlen - protolen - 1); 1782 1783 if (DB_REF(mp) > 1) { 1784 tmp = copymsg(state->sa_mqhead); 1785 freemsg(state->sa_mqhead); 1786 if ((state->sa_mqhead = tmp) == NULL) { 1787 return (send_frame); 1788 } 1789 } 1790 1791 if (state->sa_mqhead->b_rptr[0] == PPP_ALLSTATIONS) 1792 state->sa_mqhead->b_rptr += 2; 1793 1794 linkb(new_frame, state->sa_mqhead); 1795 state->sa_mqtail = state->sa_mqhead; 1796 /* point mqtail to the last mblk_t */ 1797 while (state->sa_mqtail->b_cont != NULL) 1798 state->sa_mqtail = state->sa_mqtail->b_cont; 1799 1800 /* change state->sa_mqhead */ 1801 state->sa_mqhead = new_frame; 1802 1803 } 1804 1805 if (state->sa_proto == proto) { 1806 1807 /* Check if the mblk_t is being referenced */ 1808 if (DB_REF(mp) > 1) { 1809 tmp = copymsg(mp); 1810 freemsg(mp); 1811 if ((mp = tmp) == NULL) { 1812 return (send_frame); 1813 } 1814 } 1815 1816 /* 1817 * match,can remove the protocol field 1818 * and write data there 1819 */ 1820 mp->b_rptr += hdrlen; 1821 /* 1822 * protolen - 1 ,because the the byte with 1823 * the PFF bit and the length field have 1824 * to added 1825 */ 1826 mp->b_rptr += (protolen - 1); 1827 *mp->b_rptr = (len - protolen) & 0xff; 1828 1829 } else { 1830 /* 1831 * no match, there are three options 1832 * 1. write in mp 1833 * 2. write in mqtail 1834 * 3. alloc a new blk for just one byte 1835 */ 1836 /* Check if the mblk_t is being referenced */ 1837 if (DB_REF(mp) > 1) { 1838 tmp = copymsg(mp); 1839 freemsg(mp); 1840 if ((mp = tmp) == NULL) { 1841 return (send_frame); 1842 } 1843 } 1844 1845 if (hdrlen != 0) { 1846 1847 mp->b_rptr += (hdrlen-1); 1848 *mp->b_rptr = PFF | (len); 1849 1850 } else if (state->sa_mqtail->b_wptr < 1851 DB_LIM(state->sa_mqtail)) { 1852 *state->sa_mqtail->b_wptr++ = PFF |len; 1853 } else { 1854 /* allocate a new mblk & add the byte */ 1855 /* write the data */ 1856 if ((new_frame = allocb(1, BPRI_MED)) 1857 == NULL) { 1858 freemsg(mp); 1859 return (send_frame); 1860 } 1861 *new_frame->b_wptr++ = PFF | (len); 1862 linkb(state->sa_mqtail, new_frame); 1863 } 1864 1865 /* update proto */ 1866 state->sa_proto = proto; 1867 } 1868 1869 linkb(state->sa_mqtail, mp); 1870 state->sa_mqtail = mp; 1871 while (state->sa_mqtail->b_cont != NULL) 1872 state->sa_mqtail = state->sa_mqtail->b_cont; 1873 state->sa_mqlen += nlen; 1874 1875 } else { 1876 state->sa_mqhead = mp; 1877 state->sa_mqlen = len + protolen + 1; 1878 state->sa_proto = proto; 1879 } 1880 1881 if (state->sa_timeout_id == 0) { 1882 state->sa_timeout_id = qtimeout(q, spppasyn_timer, q, 1883 (drv_usectohz(state->sa_timeout_usec))); 1884 } 1885 return (send_frame); 1886 } 1887 1888 /* 1889 * Called from receive frame, this routine checks if it is a PPP_MUX 1890 * packet and demuxes it. The returned pointer is a chain of mblks 1891 * using b_next and representing the demultiplexed packets. 1892 */ 1893 static mblk_t * 1894 spppasyn_inpkt(queue_t *q, mblk_t *mp) 1895 { 1896 sppp_ahdlc_t *state = (sppp_ahdlc_t *)q->q_ptr; 1897 ushort_t proto; 1898 ushort_t prev_proto; 1899 uint32_t len; /* length of subframe */ 1900 uchar_t muxhdr; 1901 mblk_t *hdrmp; 1902 mblk_t *subframe; 1903 mblk_t *retmp; 1904 1905 if (!(mp->b_rptr[0] & PFF)) { 1906 KINCR(pks_inmuxerrs); 1907 (void) putnextctl1(q, M_CTL, PPPCTL_IERROR); 1908 freemsg(mp); 1909 return (NULL); 1910 } 1911 1912 /* initialise the Last protocol and protocol length */ 1913 prev_proto = 0; 1914 1915 /* 1916 * Taking into granted that the decoded frame is contiguous 1917 */ 1918 retmp = NULL; 1919 while (mp->b_rptr < mp->b_wptr) { 1920 1921 /* 1922 * get the last protocol, protocol length 1923 * and the length of the message 1924 */ 1925 1926 /* protocol field flag and length */ 1927 muxhdr = mp->b_rptr[0]; 1928 len = muxhdr & ~PFF; 1929 1930 mp->b_rptr++; 1931 1932 /* check if there and enough bytes left in pkt */ 1933 if (MBLKL(mp) < len) { 1934 KINCR(pks_inmuxerrs); 1935 (void) putnextctl1(q, M_CTL, PPPCTL_IERROR); 1936 break; 1937 } 1938 1939 /* allocate memory for the header length */ 1940 if ((hdrmp = allocb(PPP_HDRLEN, BPRI_MED)) == NULL) { 1941 KINCR(pks_inallocfails); 1942 break; 1943 } 1944 1945 /* add the ppp header to the pkt */ 1946 *hdrmp->b_wptr++ = PPP_ALLSTATIONS; 1947 *hdrmp->b_wptr++ = PPP_UI; 1948 1949 /* check if the protocol field flag is set */ 1950 if (muxhdr & PFF) { 1951 1952 /* get the protocol */ 1953 proto = MSG_BYTE(mp, 0); 1954 if ((proto & 1) == 0) 1955 proto = (proto << 8) + MSG_BYTE(mp, 1); 1956 1957 /* reset values */ 1958 prev_proto = proto; 1959 } else { 1960 if (!IS_DECOMP_PROT(state)) 1961 *hdrmp->b_wptr++ = prev_proto >> 8; 1962 *hdrmp->b_wptr++ = (prev_proto & 0xff); 1963 } 1964 1965 /* get the payload from the MUXed packet */ 1966 subframe = dupmsg(mp); 1967 subframe->b_wptr = mp->b_rptr + len; 1968 1969 /* link the subframe to the new frame */ 1970 linkb(hdrmp, subframe); 1971 1972 /* do a putnext */ 1973 retmp = sppp_mappend(retmp, hdrmp); 1974 1975 /* move the read pointer beyond this subframe */ 1976 mp->b_rptr += len; 1977 } 1978 1979 freemsg(mp); 1980 return (retmp); 1981 } 1982 1983 1984 /* 1985 * timer routine which sends out the queued pkts * 1986 */ 1987 static void 1988 spppasyn_timer(void *arg) 1989 { 1990 queue_t *q; 1991 sppp_ahdlc_t *state; 1992 mblk_t *mp; 1993 1994 ASSERT(arg); 1995 q = (queue_t *)arg; 1996 state = (sppp_ahdlc_t *)q->q_ptr; 1997 1998 if (state->sa_mqhead != NULL) { 1999 /* increment counter */ 2000 if (state->sa_mqtail != NULL) 2001 KINCR(pks_sentmux); 2002 if ((mp = ahdlc_encode(q, state->sa_mqhead)) != NULL) 2003 putnext(q, mp); 2004 /* reset the state values over here */ 2005 RESET_MUX_VALUES(state); 2006 } 2007 /* clear timeout_id */ 2008 state->sa_timeout_id = 0; 2009 } 2010