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