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