1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * This module implements the services provided by the rlogin daemon 31*7c478bd9Sstevel@tonic-gate * after the connection is set up. Mainly this means responding to 32*7c478bd9Sstevel@tonic-gate * interrupts and window size changes. It begins operation in "disabled" 33*7c478bd9Sstevel@tonic-gate * state, and sends a T_DATA_REQ to the daemon to indicate that it is 34*7c478bd9Sstevel@tonic-gate * in place and ready to be enabled. The daemon can then know when all 35*7c478bd9Sstevel@tonic-gate * data which sneaked passed rlmod (before it was pushed) has been received. 36*7c478bd9Sstevel@tonic-gate * The daemon may process this data, or send data back to be inserted in 37*7c478bd9Sstevel@tonic-gate * the read queue at the head with the RL_IOC_ENABLE ioctl. 38*7c478bd9Sstevel@tonic-gate */ 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/stream.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/stropts.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/strsun.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/tihdr.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/ptem.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 54*7c478bd9Sstevel@tonic-gate #include <sys/vtrace.h> 55*7c478bd9Sstevel@tonic-gate #include <sys/rlioctl.h> 56*7c478bd9Sstevel@tonic-gate #include <sys/termios.h> 57*7c478bd9Sstevel@tonic-gate #include <sys/termio.h> 58*7c478bd9Sstevel@tonic-gate #include <sys/byteorder.h> 59*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 60*7c478bd9Sstevel@tonic-gate #include <sys/cryptmod.h> 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate extern struct streamtab rloginmodinfo; 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate static struct fmodsw fsw = { 65*7c478bd9Sstevel@tonic-gate "rlmod", 66*7c478bd9Sstevel@tonic-gate &rloginmodinfo, 67*7c478bd9Sstevel@tonic-gate D_MTQPAIR | D_MP 68*7c478bd9Sstevel@tonic-gate }; 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate /* 71*7c478bd9Sstevel@tonic-gate * Module linkage information for the kernel. 72*7c478bd9Sstevel@tonic-gate */ 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate static struct modlstrmod modlstrmod = { 75*7c478bd9Sstevel@tonic-gate &mod_strmodops, 76*7c478bd9Sstevel@tonic-gate "rloginmod module", 77*7c478bd9Sstevel@tonic-gate &fsw 78*7c478bd9Sstevel@tonic-gate }; 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = { 81*7c478bd9Sstevel@tonic-gate MODREV_1, &modlstrmod, NULL 82*7c478bd9Sstevel@tonic-gate }; 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate int 86*7c478bd9Sstevel@tonic-gate _init(void) 87*7c478bd9Sstevel@tonic-gate { 88*7c478bd9Sstevel@tonic-gate return (mod_install(&modlinkage)); 89*7c478bd9Sstevel@tonic-gate } 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate int 92*7c478bd9Sstevel@tonic-gate _fini(void) 93*7c478bd9Sstevel@tonic-gate { 94*7c478bd9Sstevel@tonic-gate return (mod_remove(&modlinkage)); 95*7c478bd9Sstevel@tonic-gate } 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate int 98*7c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop) 99*7c478bd9Sstevel@tonic-gate { 100*7c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 101*7c478bd9Sstevel@tonic-gate } 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate struct rlmod_info; /* forward reference for function prototype */ 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate static int rlmodopen(queue_t *, dev_t *, int, int, cred_t *); 106*7c478bd9Sstevel@tonic-gate static int rlmodclose(queue_t *, int, cred_t *); 107*7c478bd9Sstevel@tonic-gate static int rlmodrput(queue_t *, mblk_t *); 108*7c478bd9Sstevel@tonic-gate static int rlmodrsrv(queue_t *); 109*7c478bd9Sstevel@tonic-gate static int rlmodwput(queue_t *, mblk_t *); 110*7c478bd9Sstevel@tonic-gate static int rlmodwsrv(queue_t *); 111*7c478bd9Sstevel@tonic-gate static int rlmodrmsg(queue_t *, mblk_t *); 112*7c478bd9Sstevel@tonic-gate static mblk_t *make_expmblk(char); 113*7c478bd9Sstevel@tonic-gate static int rlwinctl(queue_t *, mblk_t *); 114*7c478bd9Sstevel@tonic-gate static mblk_t *rlwinsetup(queue_t *, mblk_t *, unsigned char *); 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate static void rlmod_timer(void *); 117*7c478bd9Sstevel@tonic-gate static void rlmod_buffer(void *); 118*7c478bd9Sstevel@tonic-gate static boolean_t tty_flow(queue_t *, struct rlmod_info *, mblk_t *); 119*7c478bd9Sstevel@tonic-gate static boolean_t rlmodwioctl(queue_t *, mblk_t *); 120*7c478bd9Sstevel@tonic-gate static void recover(queue_t *, mblk_t *, size_t); 121*7c478bd9Sstevel@tonic-gate static void recover1(queue_t *, size_t); 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate #define RLMOD_ID 106 124*7c478bd9Sstevel@tonic-gate #define SIMWAIT (1*hz) 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate /* 127*7c478bd9Sstevel@tonic-gate * Stream module data structure definitions. 128*7c478bd9Sstevel@tonic-gate * generally pushed onto tcp by rlogin daemon 129*7c478bd9Sstevel@tonic-gate * 130*7c478bd9Sstevel@tonic-gate */ 131*7c478bd9Sstevel@tonic-gate static struct module_info rloginmodiinfo = { 132*7c478bd9Sstevel@tonic-gate RLMOD_ID, /* module id number */ 133*7c478bd9Sstevel@tonic-gate "rlmod", /* module name */ 134*7c478bd9Sstevel@tonic-gate 0, /* minimum packet size */ 135*7c478bd9Sstevel@tonic-gate INFPSZ, /* maximum packet size */ 136*7c478bd9Sstevel@tonic-gate 512, /* hi-water mark */ 137*7c478bd9Sstevel@tonic-gate 256 /* lo-water mark */ 138*7c478bd9Sstevel@tonic-gate }; 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate static struct qinit rloginmodrinit = { 141*7c478bd9Sstevel@tonic-gate rlmodrput, 142*7c478bd9Sstevel@tonic-gate rlmodrsrv, 143*7c478bd9Sstevel@tonic-gate rlmodopen, 144*7c478bd9Sstevel@tonic-gate rlmodclose, 145*7c478bd9Sstevel@tonic-gate nulldev, 146*7c478bd9Sstevel@tonic-gate &rloginmodiinfo, 147*7c478bd9Sstevel@tonic-gate NULL 148*7c478bd9Sstevel@tonic-gate }; 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate static struct qinit rloginmodwinit = { 151*7c478bd9Sstevel@tonic-gate rlmodwput, 152*7c478bd9Sstevel@tonic-gate rlmodwsrv, 153*7c478bd9Sstevel@tonic-gate NULL, 154*7c478bd9Sstevel@tonic-gate NULL, 155*7c478bd9Sstevel@tonic-gate nulldev, 156*7c478bd9Sstevel@tonic-gate &rloginmodiinfo, 157*7c478bd9Sstevel@tonic-gate NULL 158*7c478bd9Sstevel@tonic-gate }; 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate struct streamtab rloginmodinfo = { 161*7c478bd9Sstevel@tonic-gate &rloginmodrinit, 162*7c478bd9Sstevel@tonic-gate &rloginmodwinit, 163*7c478bd9Sstevel@tonic-gate NULL, 164*7c478bd9Sstevel@tonic-gate NULL 165*7c478bd9Sstevel@tonic-gate }; 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate /* 168*7c478bd9Sstevel@tonic-gate * Per-instance state struct for the rloginmod module. 169*7c478bd9Sstevel@tonic-gate */ 170*7c478bd9Sstevel@tonic-gate struct rlmod_info 171*7c478bd9Sstevel@tonic-gate { 172*7c478bd9Sstevel@tonic-gate int flags; 173*7c478bd9Sstevel@tonic-gate bufcall_id_t wbufcid; 174*7c478bd9Sstevel@tonic-gate bufcall_id_t rbufcid; 175*7c478bd9Sstevel@tonic-gate timeout_id_t wtimoutid; 176*7c478bd9Sstevel@tonic-gate timeout_id_t rtimoutid; 177*7c478bd9Sstevel@tonic-gate int rl_expdat; 178*7c478bd9Sstevel@tonic-gate int stopmode; 179*7c478bd9Sstevel@tonic-gate mblk_t *unbind_mp; 180*7c478bd9Sstevel@tonic-gate char startc; 181*7c478bd9Sstevel@tonic-gate char stopc; 182*7c478bd9Sstevel@tonic-gate char oobdata[1]; 183*7c478bd9Sstevel@tonic-gate mblk_t *wndw_sz_hd_mp; 184*7c478bd9Sstevel@tonic-gate }; 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate /* 187*7c478bd9Sstevel@tonic-gate * Flag used in flags 188*7c478bd9Sstevel@tonic-gate */ 189*7c478bd9Sstevel@tonic-gate #define RL_DISABLED 0x1 190*7c478bd9Sstevel@tonic-gate #define RL_IOCPASSTHRU 0x2 191*7c478bd9Sstevel@tonic-gate 192*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 193*7c478bd9Sstevel@tonic-gate static void 194*7c478bd9Sstevel@tonic-gate dummy_callback(void *arg) 195*7c478bd9Sstevel@tonic-gate {} 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate /* 198*7c478bd9Sstevel@tonic-gate * rlmodopen - open routine gets called when the 199*7c478bd9Sstevel@tonic-gate * module gets pushed onto the stream. 200*7c478bd9Sstevel@tonic-gate */ 201*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 202*7c478bd9Sstevel@tonic-gate static int 203*7c478bd9Sstevel@tonic-gate rlmodopen(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *cred) 204*7c478bd9Sstevel@tonic-gate { 205*7c478bd9Sstevel@tonic-gate struct rlmod_info *rmip; 206*7c478bd9Sstevel@tonic-gate union T_primitives *tp; 207*7c478bd9Sstevel@tonic-gate mblk_t *bp; 208*7c478bd9Sstevel@tonic-gate int error; 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate if (sflag != MODOPEN) 211*7c478bd9Sstevel@tonic-gate return (EINVAL); 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate if (q->q_ptr != NULL) { 214*7c478bd9Sstevel@tonic-gate /* It's already attached. */ 215*7c478bd9Sstevel@tonic-gate return (0); 216*7c478bd9Sstevel@tonic-gate } 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate /* 219*7c478bd9Sstevel@tonic-gate * Allocate state structure. 220*7c478bd9Sstevel@tonic-gate */ 221*7c478bd9Sstevel@tonic-gate rmip = kmem_zalloc(sizeof (*rmip), KM_SLEEP); 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate /* 224*7c478bd9Sstevel@tonic-gate * Cross-link. 225*7c478bd9Sstevel@tonic-gate */ 226*7c478bd9Sstevel@tonic-gate q->q_ptr = rmip; 227*7c478bd9Sstevel@tonic-gate WR(q)->q_ptr = rmip; 228*7c478bd9Sstevel@tonic-gate rmip->rl_expdat = 0; 229*7c478bd9Sstevel@tonic-gate rmip->stopmode = TIOCPKT_DOSTOP; 230*7c478bd9Sstevel@tonic-gate rmip->startc = CTRL('q'); 231*7c478bd9Sstevel@tonic-gate rmip->stopc = CTRL('s'); 232*7c478bd9Sstevel@tonic-gate rmip->oobdata[0] = (char)TIOCPKT_WINDOW; 233*7c478bd9Sstevel@tonic-gate rmip->wndw_sz_hd_mp = NULL; 234*7c478bd9Sstevel@tonic-gate /* 235*7c478bd9Sstevel@tonic-gate * Allow only non-M_DATA blocks to pass up to in.rlogind until 236*7c478bd9Sstevel@tonic-gate * it is ready for M_DATA (indicated by RL_IOC_ENABLE). 237*7c478bd9Sstevel@tonic-gate */ 238*7c478bd9Sstevel@tonic-gate rmip->flags |= RL_DISABLED; 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate qprocson(q); 241*7c478bd9Sstevel@tonic-gate 242*7c478bd9Sstevel@tonic-gate /* 243*7c478bd9Sstevel@tonic-gate * Since TCP operates in the TLI-inspired brain-dead fashion, 244*7c478bd9Sstevel@tonic-gate * the connection will revert to bound state if the connection 245*7c478bd9Sstevel@tonic-gate * is reset by the client. We must send a T_UNBIND_REQ in 246*7c478bd9Sstevel@tonic-gate * that case so the port doesn't get "wedged" (preventing 247*7c478bd9Sstevel@tonic-gate * inetd from being able to restart the listener). Allocate 248*7c478bd9Sstevel@tonic-gate * it here, so that we don't need to worry about allocb() 249*7c478bd9Sstevel@tonic-gate * failures later. 250*7c478bd9Sstevel@tonic-gate */ 251*7c478bd9Sstevel@tonic-gate while ((rmip->unbind_mp = allocb(sizeof (union T_primitives), 252*7c478bd9Sstevel@tonic-gate BPRI_HI)) == NULL) { 253*7c478bd9Sstevel@tonic-gate bufcall_id_t id = qbufcall(q, sizeof (union T_primitives), 254*7c478bd9Sstevel@tonic-gate BPRI_HI, dummy_callback, NULL); 255*7c478bd9Sstevel@tonic-gate if (!qwait_sig(q)) { 256*7c478bd9Sstevel@tonic-gate qunbufcall(q, id); 257*7c478bd9Sstevel@tonic-gate error = EINTR; 258*7c478bd9Sstevel@tonic-gate goto fail; 259*7c478bd9Sstevel@tonic-gate } 260*7c478bd9Sstevel@tonic-gate qunbufcall(q, id); 261*7c478bd9Sstevel@tonic-gate } 262*7c478bd9Sstevel@tonic-gate rmip->unbind_mp->b_wptr = rmip->unbind_mp->b_rptr + 263*7c478bd9Sstevel@tonic-gate sizeof (struct T_unbind_req); 264*7c478bd9Sstevel@tonic-gate rmip->unbind_mp->b_datap->db_type = M_PROTO; 265*7c478bd9Sstevel@tonic-gate tp = (union T_primitives *)rmip->unbind_mp->b_rptr; 266*7c478bd9Sstevel@tonic-gate tp->type = T_UNBIND_REQ; 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate /* 269*7c478bd9Sstevel@tonic-gate * Send a M_PROTO msg of type T_DATA_REQ (this is unique for 270*7c478bd9Sstevel@tonic-gate * read queue since only write queue can get T_DATA_REQ). 271*7c478bd9Sstevel@tonic-gate * Readstream routine in the daemon will do a getmsg() till 272*7c478bd9Sstevel@tonic-gate * it receives this proto message. 273*7c478bd9Sstevel@tonic-gate */ 274*7c478bd9Sstevel@tonic-gate while ((bp = allocb(sizeof (union T_primitives), BPRI_HI)) == NULL) { 275*7c478bd9Sstevel@tonic-gate bufcall_id_t id = qbufcall(q, sizeof (union T_primitives), 276*7c478bd9Sstevel@tonic-gate BPRI_HI, dummy_callback, NULL); 277*7c478bd9Sstevel@tonic-gate if (!qwait_sig(q)) { 278*7c478bd9Sstevel@tonic-gate qunbufcall(q, id); 279*7c478bd9Sstevel@tonic-gate error = EINTR; 280*7c478bd9Sstevel@tonic-gate goto fail; 281*7c478bd9Sstevel@tonic-gate } 282*7c478bd9Sstevel@tonic-gate qunbufcall(q, id); 283*7c478bd9Sstevel@tonic-gate } 284*7c478bd9Sstevel@tonic-gate bp->b_datap->db_type = M_PROTO; 285*7c478bd9Sstevel@tonic-gate bp->b_wptr = bp->b_rptr + sizeof (union T_primitives); 286*7c478bd9Sstevel@tonic-gate tp = (union T_primitives *)bp->b_rptr; 287*7c478bd9Sstevel@tonic-gate tp->type = T_DATA_REQ; 288*7c478bd9Sstevel@tonic-gate tp->data_req.MORE_flag = 0; 289*7c478bd9Sstevel@tonic-gate 290*7c478bd9Sstevel@tonic-gate putnext(q, bp); 291*7c478bd9Sstevel@tonic-gate return (0); 292*7c478bd9Sstevel@tonic-gate fail: 293*7c478bd9Sstevel@tonic-gate qprocsoff(q); 294*7c478bd9Sstevel@tonic-gate if (rmip->unbind_mp != NULL) { 295*7c478bd9Sstevel@tonic-gate freemsg(rmip->unbind_mp); 296*7c478bd9Sstevel@tonic-gate } 297*7c478bd9Sstevel@tonic-gate kmem_free(rmip, sizeof (struct rlmod_info)); 298*7c478bd9Sstevel@tonic-gate q->q_ptr = NULL; 299*7c478bd9Sstevel@tonic-gate WR(q)->q_ptr = NULL; 300*7c478bd9Sstevel@tonic-gate return (error); 301*7c478bd9Sstevel@tonic-gate } 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate /* 305*7c478bd9Sstevel@tonic-gate * rlmodclose - This routine gets called when the module 306*7c478bd9Sstevel@tonic-gate * gets popped off of the stream. 307*7c478bd9Sstevel@tonic-gate */ 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 310*7c478bd9Sstevel@tonic-gate static int 311*7c478bd9Sstevel@tonic-gate rlmodclose(queue_t *q, int flag, cred_t *credp) 312*7c478bd9Sstevel@tonic-gate { 313*7c478bd9Sstevel@tonic-gate struct rlmod_info *rmip = (struct rlmod_info *)q->q_ptr; 314*7c478bd9Sstevel@tonic-gate mblk_t *mp; 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate /* 317*7c478bd9Sstevel@tonic-gate * Flush any write-side data downstream. Ignoring flow 318*7c478bd9Sstevel@tonic-gate * control at this point is known to be safe because the 319*7c478bd9Sstevel@tonic-gate * M_HANGUP below poisons the stream such that no modules can 320*7c478bd9Sstevel@tonic-gate * be pushed again. 321*7c478bd9Sstevel@tonic-gate */ 322*7c478bd9Sstevel@tonic-gate while (mp = getq(WR(q))) 323*7c478bd9Sstevel@tonic-gate putnext(WR(q), mp); 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate /* Poison the stream head so that we can't be pushed again. */ 326*7c478bd9Sstevel@tonic-gate (void) putnextctl(q, M_HANGUP); 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate qprocsoff(q); 329*7c478bd9Sstevel@tonic-gate if (rmip->wbufcid) { 330*7c478bd9Sstevel@tonic-gate qunbufcall(q, rmip->wbufcid); 331*7c478bd9Sstevel@tonic-gate rmip->wbufcid = 0; 332*7c478bd9Sstevel@tonic-gate } 333*7c478bd9Sstevel@tonic-gate if (rmip->rbufcid) { 334*7c478bd9Sstevel@tonic-gate qunbufcall(q, rmip->rbufcid); 335*7c478bd9Sstevel@tonic-gate rmip->rbufcid = 0; 336*7c478bd9Sstevel@tonic-gate } 337*7c478bd9Sstevel@tonic-gate if (rmip->wtimoutid) { 338*7c478bd9Sstevel@tonic-gate (void) quntimeout(q, rmip->wtimoutid); 339*7c478bd9Sstevel@tonic-gate rmip->wtimoutid = 0; 340*7c478bd9Sstevel@tonic-gate } 341*7c478bd9Sstevel@tonic-gate if (rmip->rtimoutid) { 342*7c478bd9Sstevel@tonic-gate (void) quntimeout(q, rmip->rtimoutid); 343*7c478bd9Sstevel@tonic-gate rmip->rtimoutid = 0; 344*7c478bd9Sstevel@tonic-gate } 345*7c478bd9Sstevel@tonic-gate 346*7c478bd9Sstevel@tonic-gate if (rmip->unbind_mp != NULL) { 347*7c478bd9Sstevel@tonic-gate freemsg(rmip->unbind_mp); 348*7c478bd9Sstevel@tonic-gate } 349*7c478bd9Sstevel@tonic-gate 350*7c478bd9Sstevel@tonic-gate if (rmip->wndw_sz_hd_mp != NULL) { 351*7c478bd9Sstevel@tonic-gate freemsg(rmip->wndw_sz_hd_mp); 352*7c478bd9Sstevel@tonic-gate } 353*7c478bd9Sstevel@tonic-gate 354*7c478bd9Sstevel@tonic-gate kmem_free(q->q_ptr, sizeof (struct rlmod_info)); 355*7c478bd9Sstevel@tonic-gate q->q_ptr = WR(q)->q_ptr = NULL; 356*7c478bd9Sstevel@tonic-gate return (0); 357*7c478bd9Sstevel@tonic-gate } 358*7c478bd9Sstevel@tonic-gate 359*7c478bd9Sstevel@tonic-gate /* 360*7c478bd9Sstevel@tonic-gate * rlmodrput - Module read queue put procedure. 361*7c478bd9Sstevel@tonic-gate * This is called from the module or 362*7c478bd9Sstevel@tonic-gate * driver downstream. 363*7c478bd9Sstevel@tonic-gate */ 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate static int 366*7c478bd9Sstevel@tonic-gate rlmodrput(queue_t *q, mblk_t *mp) 367*7c478bd9Sstevel@tonic-gate { 368*7c478bd9Sstevel@tonic-gate struct rlmod_info *rmip = (struct rlmod_info *)q->q_ptr; 369*7c478bd9Sstevel@tonic-gate union T_primitives *tip; 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate TRACE_2(TR_FAC_RLOGINP, TR_RLOGINP_RPUT_IN, "rlmodrput start: " 372*7c478bd9Sstevel@tonic-gate "q %p, mp %p", q, mp); 373*7c478bd9Sstevel@tonic-gate 374*7c478bd9Sstevel@tonic-gate 375*7c478bd9Sstevel@tonic-gate /* if low (normal) priority... */ 376*7c478bd9Sstevel@tonic-gate if ((mp->b_datap->db_type < QPCTL) && 377*7c478bd9Sstevel@tonic-gate /* ...and data is already queued... */ 378*7c478bd9Sstevel@tonic-gate ((q->q_first) || 379*7c478bd9Sstevel@tonic-gate /* ...or currently disabled and this is M_DATA... */ 380*7c478bd9Sstevel@tonic-gate ((rmip->flags & RL_DISABLED) && 381*7c478bd9Sstevel@tonic-gate (mp->b_datap->db_type == M_DATA)))) { 382*7c478bd9Sstevel@tonic-gate /* ...delay delivery of the message */ 383*7c478bd9Sstevel@tonic-gate (void) putq(q, mp); 384*7c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_RPUT_OUT, 385*7c478bd9Sstevel@tonic-gate "rlmodrput end: q %p, mp %p, %s", q, mp, "flow"); 386*7c478bd9Sstevel@tonic-gate return (0); 387*7c478bd9Sstevel@tonic-gate } 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) { 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate case M_PROTO: 392*7c478bd9Sstevel@tonic-gate case M_PCPROTO: 393*7c478bd9Sstevel@tonic-gate tip = (union T_primitives *)mp->b_rptr; 394*7c478bd9Sstevel@tonic-gate switch (tip->type) { 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate case T_ORDREL_IND: 397*7c478bd9Sstevel@tonic-gate case T_DISCON_IND: 398*7c478bd9Sstevel@tonic-gate /* Make into M_HANGUP and putnext */ 399*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_HANGUP; 400*7c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr; 401*7c478bd9Sstevel@tonic-gate if (mp->b_cont) { 402*7c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 403*7c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 404*7c478bd9Sstevel@tonic-gate } 405*7c478bd9Sstevel@tonic-gate /* 406*7c478bd9Sstevel@tonic-gate * If we haven't already, send T_UNBIND_REQ to prevent 407*7c478bd9Sstevel@tonic-gate * TCP from going into "BOUND" state and locking up the 408*7c478bd9Sstevel@tonic-gate * port. 409*7c478bd9Sstevel@tonic-gate */ 410*7c478bd9Sstevel@tonic-gate if (tip->type == T_DISCON_IND && rmip->unbind_mp != 411*7c478bd9Sstevel@tonic-gate NULL) { 412*7c478bd9Sstevel@tonic-gate putnext(q, mp); 413*7c478bd9Sstevel@tonic-gate qreply(q, rmip->unbind_mp); 414*7c478bd9Sstevel@tonic-gate rmip->unbind_mp = NULL; 415*7c478bd9Sstevel@tonic-gate } else { 416*7c478bd9Sstevel@tonic-gate putnext(q, mp); 417*7c478bd9Sstevel@tonic-gate } 418*7c478bd9Sstevel@tonic-gate break; 419*7c478bd9Sstevel@tonic-gate 420*7c478bd9Sstevel@tonic-gate /* 421*7c478bd9Sstevel@tonic-gate * We only get T_OK_ACK when we issue the unbind, and it can 422*7c478bd9Sstevel@tonic-gate * be ignored safely. 423*7c478bd9Sstevel@tonic-gate */ 424*7c478bd9Sstevel@tonic-gate case T_OK_ACK: 425*7c478bd9Sstevel@tonic-gate ASSERT(rmip->unbind_mp == NULL); 426*7c478bd9Sstevel@tonic-gate freemsg(mp); 427*7c478bd9Sstevel@tonic-gate break; 428*7c478bd9Sstevel@tonic-gate 429*7c478bd9Sstevel@tonic-gate default: 430*7c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, 431*7c478bd9Sstevel@tonic-gate "rlmodrput: got 0x%x type M_PROTO/M_PCPROTO msg", 432*7c478bd9Sstevel@tonic-gate tip->type); 433*7c478bd9Sstevel@tonic-gate freemsg(mp); 434*7c478bd9Sstevel@tonic-gate } 435*7c478bd9Sstevel@tonic-gate break; 436*7c478bd9Sstevel@tonic-gate 437*7c478bd9Sstevel@tonic-gate case M_DATA: 438*7c478bd9Sstevel@tonic-gate if (canputnext(q) && q->q_first == NULL) { 439*7c478bd9Sstevel@tonic-gate (void) rlmodrmsg(q, mp); 440*7c478bd9Sstevel@tonic-gate } else { 441*7c478bd9Sstevel@tonic-gate (void) putq(q, mp); 442*7c478bd9Sstevel@tonic-gate } 443*7c478bd9Sstevel@tonic-gate break; 444*7c478bd9Sstevel@tonic-gate 445*7c478bd9Sstevel@tonic-gate case M_FLUSH: 446*7c478bd9Sstevel@tonic-gate /* 447*7c478bd9Sstevel@tonic-gate * Since M_FLUSH came from TCP, we mark it bound for 448*7c478bd9Sstevel@tonic-gate * daemon, not tty. This only happens when TCP expects 449*7c478bd9Sstevel@tonic-gate * to do a connection reset. 450*7c478bd9Sstevel@tonic-gate */ 451*7c478bd9Sstevel@tonic-gate mp->b_flag |= MSGMARK; 452*7c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHR) 453*7c478bd9Sstevel@tonic-gate flushq(q, FLUSHALL); 454*7c478bd9Sstevel@tonic-gate 455*7c478bd9Sstevel@tonic-gate putnext(q, mp); 456*7c478bd9Sstevel@tonic-gate break; 457*7c478bd9Sstevel@tonic-gate 458*7c478bd9Sstevel@tonic-gate case M_PCSIG: 459*7c478bd9Sstevel@tonic-gate case M_ERROR: 460*7c478bd9Sstevel@tonic-gate case M_IOCACK: 461*7c478bd9Sstevel@tonic-gate case M_IOCNAK: 462*7c478bd9Sstevel@tonic-gate case M_SETOPTS: 463*7c478bd9Sstevel@tonic-gate if (mp->b_datap->db_type <= QPCTL && !canputnext(q)) 464*7c478bd9Sstevel@tonic-gate (void) putq(q, mp); 465*7c478bd9Sstevel@tonic-gate else 466*7c478bd9Sstevel@tonic-gate putnext(q, mp); 467*7c478bd9Sstevel@tonic-gate break; 468*7c478bd9Sstevel@tonic-gate 469*7c478bd9Sstevel@tonic-gate default: 470*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 471*7c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "rlmodrput: unexpected msg type 0x%x", 472*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type); 473*7c478bd9Sstevel@tonic-gate #endif 474*7c478bd9Sstevel@tonic-gate freemsg(mp); 475*7c478bd9Sstevel@tonic-gate } 476*7c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_RPUT_OUT, "rlmodrput end: q %p, " 477*7c478bd9Sstevel@tonic-gate "mp %p, %s", q, mp, "done"); 478*7c478bd9Sstevel@tonic-gate return (0); 479*7c478bd9Sstevel@tonic-gate } 480*7c478bd9Sstevel@tonic-gate 481*7c478bd9Sstevel@tonic-gate /* 482*7c478bd9Sstevel@tonic-gate * rlmodrsrv - module read service procedure 483*7c478bd9Sstevel@tonic-gate */ 484*7c478bd9Sstevel@tonic-gate static int 485*7c478bd9Sstevel@tonic-gate rlmodrsrv(queue_t *q) 486*7c478bd9Sstevel@tonic-gate { 487*7c478bd9Sstevel@tonic-gate mblk_t *mp; 488*7c478bd9Sstevel@tonic-gate struct rlmod_info *rmip = (struct rlmod_info *)q->q_ptr; 489*7c478bd9Sstevel@tonic-gate union T_primitives *tip; 490*7c478bd9Sstevel@tonic-gate 491*7c478bd9Sstevel@tonic-gate TRACE_1(TR_FAC_RLOGINP, TR_RLOGINP_RSRV_IN, "rlmodrsrv start: " 492*7c478bd9Sstevel@tonic-gate "q %p", q); 493*7c478bd9Sstevel@tonic-gate while ((mp = getq(q)) != NULL) { 494*7c478bd9Sstevel@tonic-gate 495*7c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) { 496*7c478bd9Sstevel@tonic-gate case M_DATA: 497*7c478bd9Sstevel@tonic-gate if (rmip->flags & RL_DISABLED) { 498*7c478bd9Sstevel@tonic-gate (void) putbq(q, mp); 499*7c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_RSRV_OUT, 500*7c478bd9Sstevel@tonic-gate "rlmodrsrv end: q %p, mp %p, %s", q, mp, 501*7c478bd9Sstevel@tonic-gate "disabled"); 502*7c478bd9Sstevel@tonic-gate return (0); 503*7c478bd9Sstevel@tonic-gate } 504*7c478bd9Sstevel@tonic-gate if (!canputnext(q)) { 505*7c478bd9Sstevel@tonic-gate (void) putbq(q, mp); 506*7c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_RSRV_OUT, 507*7c478bd9Sstevel@tonic-gate "rlmodrsrv end: q %p, mp %p, %s", 508*7c478bd9Sstevel@tonic-gate q, mp, "!canputnext"); 509*7c478bd9Sstevel@tonic-gate return (0); 510*7c478bd9Sstevel@tonic-gate } 511*7c478bd9Sstevel@tonic-gate if (!rlmodrmsg(q, mp)) { 512*7c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_RSRV_OUT, 513*7c478bd9Sstevel@tonic-gate "rlmodrsrv end: q %p, mp %p, %s", 514*7c478bd9Sstevel@tonic-gate q, mp, "!rlmodrmsg"); 515*7c478bd9Sstevel@tonic-gate return (0); 516*7c478bd9Sstevel@tonic-gate } 517*7c478bd9Sstevel@tonic-gate break; 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate case M_PROTO: 520*7c478bd9Sstevel@tonic-gate tip = (union T_primitives *)mp->b_rptr; 521*7c478bd9Sstevel@tonic-gate switch (tip->type) { 522*7c478bd9Sstevel@tonic-gate 523*7c478bd9Sstevel@tonic-gate case T_ORDREL_IND: 524*7c478bd9Sstevel@tonic-gate case T_DISCON_IND: 525*7c478bd9Sstevel@tonic-gate /* Make into M_HANGUP and putnext */ 526*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_HANGUP; 527*7c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr; 528*7c478bd9Sstevel@tonic-gate if (mp->b_cont) { 529*7c478bd9Sstevel@tonic-gate freemsg(mp->b_cont); 530*7c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 531*7c478bd9Sstevel@tonic-gate } 532*7c478bd9Sstevel@tonic-gate /* 533*7c478bd9Sstevel@tonic-gate * If we haven't already, send T_UNBIND_REQ 534*7c478bd9Sstevel@tonic-gate * to prevent TCP from going into "BOUND" 535*7c478bd9Sstevel@tonic-gate * state and locking up the port. 536*7c478bd9Sstevel@tonic-gate */ 537*7c478bd9Sstevel@tonic-gate if (tip->type == T_DISCON_IND && 538*7c478bd9Sstevel@tonic-gate rmip->unbind_mp != NULL) { 539*7c478bd9Sstevel@tonic-gate putnext(q, mp); 540*7c478bd9Sstevel@tonic-gate qreply(q, rmip->unbind_mp); 541*7c478bd9Sstevel@tonic-gate rmip->unbind_mp = NULL; 542*7c478bd9Sstevel@tonic-gate } else { 543*7c478bd9Sstevel@tonic-gate putnext(q, mp); 544*7c478bd9Sstevel@tonic-gate } 545*7c478bd9Sstevel@tonic-gate break; 546*7c478bd9Sstevel@tonic-gate 547*7c478bd9Sstevel@tonic-gate /* 548*7c478bd9Sstevel@tonic-gate * We only get T_OK_ACK when we issue the unbind, and 549*7c478bd9Sstevel@tonic-gate * it can be ignored safely. 550*7c478bd9Sstevel@tonic-gate */ 551*7c478bd9Sstevel@tonic-gate case T_OK_ACK: 552*7c478bd9Sstevel@tonic-gate ASSERT(rmip->unbind_mp == NULL); 553*7c478bd9Sstevel@tonic-gate freemsg(mp); 554*7c478bd9Sstevel@tonic-gate break; 555*7c478bd9Sstevel@tonic-gate 556*7c478bd9Sstevel@tonic-gate default: 557*7c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, 558*7c478bd9Sstevel@tonic-gate "rlmodrsrv: got 0x%x type PROTO msg", 559*7c478bd9Sstevel@tonic-gate tip->type); 560*7c478bd9Sstevel@tonic-gate freemsg(mp); 561*7c478bd9Sstevel@tonic-gate } 562*7c478bd9Sstevel@tonic-gate break; 563*7c478bd9Sstevel@tonic-gate 564*7c478bd9Sstevel@tonic-gate case M_SETOPTS: 565*7c478bd9Sstevel@tonic-gate if (!canputnext(q)) { 566*7c478bd9Sstevel@tonic-gate (void) putbq(q, mp); 567*7c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_RSRV_OUT, 568*7c478bd9Sstevel@tonic-gate "rlmodrsrv end: q %p, mp %p, %s", 569*7c478bd9Sstevel@tonic-gate q, mp, "!canputnext M_SETOPTS"); 570*7c478bd9Sstevel@tonic-gate return (0); 571*7c478bd9Sstevel@tonic-gate } 572*7c478bd9Sstevel@tonic-gate putnext(q, mp); 573*7c478bd9Sstevel@tonic-gate break; 574*7c478bd9Sstevel@tonic-gate 575*7c478bd9Sstevel@tonic-gate default: 576*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 577*7c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, 578*7c478bd9Sstevel@tonic-gate "rlmodrsrv: unexpected msg type 0x%x", 579*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type); 580*7c478bd9Sstevel@tonic-gate #endif 581*7c478bd9Sstevel@tonic-gate freemsg(mp); 582*7c478bd9Sstevel@tonic-gate } 583*7c478bd9Sstevel@tonic-gate } 584*7c478bd9Sstevel@tonic-gate 585*7c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_RSRV_OUT, "rlmodrsrv end: q %p, " 586*7c478bd9Sstevel@tonic-gate "mp %p, %s", q, mp, "empty"); 587*7c478bd9Sstevel@tonic-gate 588*7c478bd9Sstevel@tonic-gate return (0); 589*7c478bd9Sstevel@tonic-gate } 590*7c478bd9Sstevel@tonic-gate 591*7c478bd9Sstevel@tonic-gate /* 592*7c478bd9Sstevel@tonic-gate * rlmodwput - Module write queue put procedure. 593*7c478bd9Sstevel@tonic-gate * All non-zero messages are send downstream unchanged 594*7c478bd9Sstevel@tonic-gate */ 595*7c478bd9Sstevel@tonic-gate static int 596*7c478bd9Sstevel@tonic-gate rlmodwput(queue_t *q, mblk_t *mp) 597*7c478bd9Sstevel@tonic-gate { 598*7c478bd9Sstevel@tonic-gate char cntl; 599*7c478bd9Sstevel@tonic-gate struct rlmod_info *rmip = (struct rlmod_info *)q->q_ptr; 600*7c478bd9Sstevel@tonic-gate mblk_t *tmpmp; 601*7c478bd9Sstevel@tonic-gate int rw; 602*7c478bd9Sstevel@tonic-gate 603*7c478bd9Sstevel@tonic-gate TRACE_2(TR_FAC_RLOGINP, TR_RLOGINP_WPUT_IN, "rlmodwput start: " 604*7c478bd9Sstevel@tonic-gate "q %p, mp %p", q, mp); 605*7c478bd9Sstevel@tonic-gate 606*7c478bd9Sstevel@tonic-gate if (rmip->rl_expdat) { 607*7c478bd9Sstevel@tonic-gate /* 608*7c478bd9Sstevel@tonic-gate * call make_expmblk to create an expedited 609*7c478bd9Sstevel@tonic-gate * message block. 610*7c478bd9Sstevel@tonic-gate */ 611*7c478bd9Sstevel@tonic-gate cntl = rmip->oobdata[0] | TIOCPKT_FLUSHWRITE; 612*7c478bd9Sstevel@tonic-gate 613*7c478bd9Sstevel@tonic-gate if (!canputnext(q)) { 614*7c478bd9Sstevel@tonic-gate (void) putq(q, mp); 615*7c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_WPUT_OUT, 616*7c478bd9Sstevel@tonic-gate "rlmodwput end: q %p, mp %p, %s", 617*7c478bd9Sstevel@tonic-gate q, mp, "expdata && !canputnext"); 618*7c478bd9Sstevel@tonic-gate return (0); 619*7c478bd9Sstevel@tonic-gate } 620*7c478bd9Sstevel@tonic-gate if ((tmpmp = make_expmblk(cntl))) { 621*7c478bd9Sstevel@tonic-gate putnext(q, tmpmp); 622*7c478bd9Sstevel@tonic-gate rmip->rl_expdat = 0; 623*7c478bd9Sstevel@tonic-gate } else { 624*7c478bd9Sstevel@tonic-gate recover1(q, sizeof (mblk_t)); /* XXX.sparker */ 625*7c478bd9Sstevel@tonic-gate } 626*7c478bd9Sstevel@tonic-gate } 627*7c478bd9Sstevel@tonic-gate 628*7c478bd9Sstevel@tonic-gate if ((q->q_first || rmip->rl_expdat) && mp->b_datap->db_type < QPCTL) { 629*7c478bd9Sstevel@tonic-gate (void) putq(q, mp); 630*7c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_WPUT_OUT, "rlmodwput end: " 631*7c478bd9Sstevel@tonic-gate "q %p, mp %p, %s", q, mp, "queued data"); 632*7c478bd9Sstevel@tonic-gate return (0); 633*7c478bd9Sstevel@tonic-gate } 634*7c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) { 635*7c478bd9Sstevel@tonic-gate 636*7c478bd9Sstevel@tonic-gate case M_DATA: 637*7c478bd9Sstevel@tonic-gate if (!canputnext(q)) 638*7c478bd9Sstevel@tonic-gate (void) putq(q, mp); 639*7c478bd9Sstevel@tonic-gate else 640*7c478bd9Sstevel@tonic-gate putnext(q, mp); 641*7c478bd9Sstevel@tonic-gate break; 642*7c478bd9Sstevel@tonic-gate 643*7c478bd9Sstevel@tonic-gate case M_FLUSH: 644*7c478bd9Sstevel@tonic-gate /* 645*7c478bd9Sstevel@tonic-gate * We must take care to create and forward out-of-band data 646*7c478bd9Sstevel@tonic-gate * indicating the flush to the far side. 647*7c478bd9Sstevel@tonic-gate */ 648*7c478bd9Sstevel@tonic-gate rw = *mp->b_rptr; 649*7c478bd9Sstevel@tonic-gate *mp->b_rptr &= ~FLUSHW; 650*7c478bd9Sstevel@tonic-gate qreply(q, mp); 651*7c478bd9Sstevel@tonic-gate if (rw & FLUSHW) { 652*7c478bd9Sstevel@tonic-gate /* 653*7c478bd9Sstevel@tonic-gate * Since all rlogin protocol data is sent in this 654*7c478bd9Sstevel@tonic-gate * direction as urgent data, and TCP does not flush 655*7c478bd9Sstevel@tonic-gate * urgent data, it is okay to actually forward this 656*7c478bd9Sstevel@tonic-gate * flush. (telmod cannot.) 657*7c478bd9Sstevel@tonic-gate */ 658*7c478bd9Sstevel@tonic-gate flushq(q, FLUSHDATA); 659*7c478bd9Sstevel@tonic-gate /* 660*7c478bd9Sstevel@tonic-gate * The putnextctl1() call can only fail if we're 661*7c478bd9Sstevel@tonic-gate * out of memory. Ideally, we might set a state 662*7c478bd9Sstevel@tonic-gate * bit and reschedule ourselves when memory 663*7c478bd9Sstevel@tonic-gate * becomes available, so we make sure not to miss 664*7c478bd9Sstevel@tonic-gate * sending the FLUSHW to TCP before the urgent 665*7c478bd9Sstevel@tonic-gate * byte. Not doing this just means in some cases 666*7c478bd9Sstevel@tonic-gate * a bit more trash passes before the flush takes 667*7c478bd9Sstevel@tonic-gate * hold. 668*7c478bd9Sstevel@tonic-gate */ 669*7c478bd9Sstevel@tonic-gate (void) putnextctl1(q, M_FLUSH, FLUSHW); 670*7c478bd9Sstevel@tonic-gate /* 671*7c478bd9Sstevel@tonic-gate * Notify peer of the write flush request. 672*7c478bd9Sstevel@tonic-gate */ 673*7c478bd9Sstevel@tonic-gate cntl = rmip->oobdata[0] | TIOCPKT_FLUSHWRITE; 674*7c478bd9Sstevel@tonic-gate if (!canputnext(q)) { 675*7c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_WPUT_OUT, 676*7c478bd9Sstevel@tonic-gate "rlmodwput end: q %p, mp %p, %s", 677*7c478bd9Sstevel@tonic-gate q, mp, "flushw && !canputnext"); 678*7c478bd9Sstevel@tonic-gate return (0); 679*7c478bd9Sstevel@tonic-gate } 680*7c478bd9Sstevel@tonic-gate if ((mp = make_expmblk(cntl)) == NULL) { 681*7c478bd9Sstevel@tonic-gate rmip->rl_expdat = 1; 682*7c478bd9Sstevel@tonic-gate recover1(q, sizeof (mblk_t)); 683*7c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_WPUT_OUT, 684*7c478bd9Sstevel@tonic-gate "rlmodwput end: q %p, mp %p, %s", 685*7c478bd9Sstevel@tonic-gate q, mp, "!make_expmblk"); 686*7c478bd9Sstevel@tonic-gate return (0); 687*7c478bd9Sstevel@tonic-gate } 688*7c478bd9Sstevel@tonic-gate putnext(q, mp); 689*7c478bd9Sstevel@tonic-gate } 690*7c478bd9Sstevel@tonic-gate break; 691*7c478bd9Sstevel@tonic-gate 692*7c478bd9Sstevel@tonic-gate case M_IOCTL: 693*7c478bd9Sstevel@tonic-gate if (!rlmodwioctl(q, mp)) 694*7c478bd9Sstevel@tonic-gate (void) putq(q, mp); 695*7c478bd9Sstevel@tonic-gate break; 696*7c478bd9Sstevel@tonic-gate 697*7c478bd9Sstevel@tonic-gate case M_PROTO: 698*7c478bd9Sstevel@tonic-gate switch (((union T_primitives *)mp->b_rptr)->type) { 699*7c478bd9Sstevel@tonic-gate case T_EXDATA_REQ: 700*7c478bd9Sstevel@tonic-gate case T_ORDREL_REQ: 701*7c478bd9Sstevel@tonic-gate case T_DISCON_REQ: 702*7c478bd9Sstevel@tonic-gate putnext(q, mp); 703*7c478bd9Sstevel@tonic-gate break; 704*7c478bd9Sstevel@tonic-gate 705*7c478bd9Sstevel@tonic-gate default: 706*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 707*7c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, 708*7c478bd9Sstevel@tonic-gate "rlmodwput: unexpected TPI primitive 0x%x", 709*7c478bd9Sstevel@tonic-gate ((union T_primitives *)mp->b_rptr)->type); 710*7c478bd9Sstevel@tonic-gate #endif 711*7c478bd9Sstevel@tonic-gate freemsg(mp); 712*7c478bd9Sstevel@tonic-gate } 713*7c478bd9Sstevel@tonic-gate break; 714*7c478bd9Sstevel@tonic-gate 715*7c478bd9Sstevel@tonic-gate case M_PCPROTO: 716*7c478bd9Sstevel@tonic-gate if (((struct T_exdata_req *)mp->b_rptr)->PRIM_type == 717*7c478bd9Sstevel@tonic-gate T_DISCON_REQ) { 718*7c478bd9Sstevel@tonic-gate putnext(q, mp); 719*7c478bd9Sstevel@tonic-gate } else { 720*7c478bd9Sstevel@tonic-gate /* XXX.sparker Log unexpected message */ 721*7c478bd9Sstevel@tonic-gate freemsg(mp); 722*7c478bd9Sstevel@tonic-gate } 723*7c478bd9Sstevel@tonic-gate break; 724*7c478bd9Sstevel@tonic-gate 725*7c478bd9Sstevel@tonic-gate default: 726*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 727*7c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, 728*7c478bd9Sstevel@tonic-gate "rlmodwput: unexpected msg type 0x%x", 729*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type); 730*7c478bd9Sstevel@tonic-gate #endif 731*7c478bd9Sstevel@tonic-gate freemsg(mp); 732*7c478bd9Sstevel@tonic-gate break; 733*7c478bd9Sstevel@tonic-gate } 734*7c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_WPUT_OUT, "rlmodwput end: " 735*7c478bd9Sstevel@tonic-gate "q %p, mp %p, %s", q, mp, "done"); 736*7c478bd9Sstevel@tonic-gate return (0); 737*7c478bd9Sstevel@tonic-gate } 738*7c478bd9Sstevel@tonic-gate 739*7c478bd9Sstevel@tonic-gate /* 740*7c478bd9Sstevel@tonic-gate * rlmodwsrv - module write service procedure 741*7c478bd9Sstevel@tonic-gate */ 742*7c478bd9Sstevel@tonic-gate static int 743*7c478bd9Sstevel@tonic-gate rlmodwsrv(queue_t *q) 744*7c478bd9Sstevel@tonic-gate { 745*7c478bd9Sstevel@tonic-gate mblk_t *mp, *tmpmp; 746*7c478bd9Sstevel@tonic-gate char cntl; 747*7c478bd9Sstevel@tonic-gate struct rlmod_info *rmip = (struct rlmod_info *)q->q_ptr; 748*7c478bd9Sstevel@tonic-gate 749*7c478bd9Sstevel@tonic-gate TRACE_1(TR_FAC_RLOGINP, TR_RLOGINP_WSRV_IN, "rlmodwsrv " 750*7c478bd9Sstevel@tonic-gate "start: q %p", q); 751*7c478bd9Sstevel@tonic-gate if (rmip->rl_expdat) { 752*7c478bd9Sstevel@tonic-gate /* 753*7c478bd9Sstevel@tonic-gate * call make_expmblk to create an expedited 754*7c478bd9Sstevel@tonic-gate * message block. 755*7c478bd9Sstevel@tonic-gate */ 756*7c478bd9Sstevel@tonic-gate cntl = rmip->oobdata[0] | TIOCPKT_FLUSHWRITE; 757*7c478bd9Sstevel@tonic-gate if (!canputnext(q)) { 758*7c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_WSRV_OUT, 759*7c478bd9Sstevel@tonic-gate "rlmodwsrv end: q %p, mp %p, %s", 760*7c478bd9Sstevel@tonic-gate q, NULL, "!canputnext && expdat"); 761*7c478bd9Sstevel@tonic-gate return (0); 762*7c478bd9Sstevel@tonic-gate } 763*7c478bd9Sstevel@tonic-gate if ((tmpmp = make_expmblk(cntl))) { 764*7c478bd9Sstevel@tonic-gate putnext(q, tmpmp); 765*7c478bd9Sstevel@tonic-gate rmip->rl_expdat = 0; 766*7c478bd9Sstevel@tonic-gate } else { 767*7c478bd9Sstevel@tonic-gate recover1(q, sizeof (mblk_t)); 768*7c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_WSRV_OUT, 769*7c478bd9Sstevel@tonic-gate "rlmodwsrv end: q %p, mp %p, %s", 770*7c478bd9Sstevel@tonic-gate q, NULL, "!make_expmblk"); 771*7c478bd9Sstevel@tonic-gate return (0); 772*7c478bd9Sstevel@tonic-gate } 773*7c478bd9Sstevel@tonic-gate } 774*7c478bd9Sstevel@tonic-gate while ((mp = getq(q)) != NULL) { 775*7c478bd9Sstevel@tonic-gate 776*7c478bd9Sstevel@tonic-gate if (!canputnext(q) || rmip->rl_expdat) { 777*7c478bd9Sstevel@tonic-gate (void) putbq(q, mp); 778*7c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_WSRV_OUT, 779*7c478bd9Sstevel@tonic-gate "rlmodwsrv end: q %p, mp %p, %s", 780*7c478bd9Sstevel@tonic-gate q, mp, "!canputnext || expdat"); 781*7c478bd9Sstevel@tonic-gate return (0); 782*7c478bd9Sstevel@tonic-gate } 783*7c478bd9Sstevel@tonic-gate if (mp->b_datap->db_type == M_IOCTL) { 784*7c478bd9Sstevel@tonic-gate if (!rlmodwioctl(q, mp)) { 785*7c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_WSRV_OUT, 786*7c478bd9Sstevel@tonic-gate "rlmodwsrv end: q %p, mp %p, %s", 787*7c478bd9Sstevel@tonic-gate q, mp, "!rlmodwioctl"); 788*7c478bd9Sstevel@tonic-gate (void) putbq(q, mp); 789*7c478bd9Sstevel@tonic-gate return (0); 790*7c478bd9Sstevel@tonic-gate } 791*7c478bd9Sstevel@tonic-gate continue; 792*7c478bd9Sstevel@tonic-gate } 793*7c478bd9Sstevel@tonic-gate putnext(q, mp); 794*7c478bd9Sstevel@tonic-gate } 795*7c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_WSRV_OUT, "rlmodwsrv end: q %p, " 796*7c478bd9Sstevel@tonic-gate "mp %p, %s", q, mp, "done"); 797*7c478bd9Sstevel@tonic-gate return (0); 798*7c478bd9Sstevel@tonic-gate } 799*7c478bd9Sstevel@tonic-gate 800*7c478bd9Sstevel@tonic-gate /* 801*7c478bd9Sstevel@tonic-gate * This routine returns a message block with an expedited 802*7c478bd9Sstevel@tonic-gate * data request 803*7c478bd9Sstevel@tonic-gate */ 804*7c478bd9Sstevel@tonic-gate static mblk_t * 805*7c478bd9Sstevel@tonic-gate make_expmblk(char cntl) 806*7c478bd9Sstevel@tonic-gate { 807*7c478bd9Sstevel@tonic-gate mblk_t *mp; 808*7c478bd9Sstevel@tonic-gate mblk_t *bp; 809*7c478bd9Sstevel@tonic-gate struct T_exdata_req *data_req; 810*7c478bd9Sstevel@tonic-gate 811*7c478bd9Sstevel@tonic-gate bp = allocb(sizeof (struct T_exdata_req), BPRI_MED); 812*7c478bd9Sstevel@tonic-gate if (bp == NULL) 813*7c478bd9Sstevel@tonic-gate return (NULL); 814*7c478bd9Sstevel@tonic-gate if ((mp = allocb(sizeof (char), BPRI_MED)) == NULL) { 815*7c478bd9Sstevel@tonic-gate freeb(bp); 816*7c478bd9Sstevel@tonic-gate return (NULL); 817*7c478bd9Sstevel@tonic-gate } 818*7c478bd9Sstevel@tonic-gate bp->b_datap->db_type = M_PROTO; 819*7c478bd9Sstevel@tonic-gate data_req = (struct T_exdata_req *)bp->b_rptr; 820*7c478bd9Sstevel@tonic-gate data_req->PRIM_type = T_EXDATA_REQ; 821*7c478bd9Sstevel@tonic-gate data_req->MORE_flag = 0; 822*7c478bd9Sstevel@tonic-gate 823*7c478bd9Sstevel@tonic-gate bp->b_wptr += sizeof (struct T_exdata_req); 824*7c478bd9Sstevel@tonic-gate /* 825*7c478bd9Sstevel@tonic-gate * Send a 1 byte data message block with appropriate 826*7c478bd9Sstevel@tonic-gate * control character. 827*7c478bd9Sstevel@tonic-gate */ 828*7c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_DATA; 829*7c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + 1; 830*7c478bd9Sstevel@tonic-gate (*(char *)(mp->b_rptr)) = cntl; 831*7c478bd9Sstevel@tonic-gate bp->b_cont = mp; 832*7c478bd9Sstevel@tonic-gate return (bp); 833*7c478bd9Sstevel@tonic-gate } 834*7c478bd9Sstevel@tonic-gate /* 835*7c478bd9Sstevel@tonic-gate * This routine parses M_DATA messages checking for window size protocol 836*7c478bd9Sstevel@tonic-gate * from a given message block. It returns TRUE if no resource exhaustion 837*7c478bd9Sstevel@tonic-gate * conditions are found. This is for use in the service procedure, which 838*7c478bd9Sstevel@tonic-gate * needs to know whether to continue, or stop processing the queue. 839*7c478bd9Sstevel@tonic-gate */ 840*7c478bd9Sstevel@tonic-gate static int 841*7c478bd9Sstevel@tonic-gate rlmodrmsg(queue_t *q, mblk_t *mp) 842*7c478bd9Sstevel@tonic-gate { 843*7c478bd9Sstevel@tonic-gate unsigned char *tmp, *tmp1; 844*7c478bd9Sstevel@tonic-gate mblk_t *newmp; 845*7c478bd9Sstevel@tonic-gate size_t sz; 846*7c478bd9Sstevel@tonic-gate ssize_t count, newcount = 0; 847*7c478bd9Sstevel@tonic-gate struct rlmod_info *rmip = (struct rlmod_info *)q->q_ptr; 848*7c478bd9Sstevel@tonic-gate 849*7c478bd9Sstevel@tonic-gate /* 850*7c478bd9Sstevel@tonic-gate * Eliminate any zero length messages here, so we don't filter EOFs 851*7c478bd9Sstevel@tonic-gate * accidentally. 852*7c478bd9Sstevel@tonic-gate */ 853*7c478bd9Sstevel@tonic-gate if (msgdsize(mp) == 0) { 854*7c478bd9Sstevel@tonic-gate ASSERT(rmip->wndw_sz_hd_mp == NULL); 855*7c478bd9Sstevel@tonic-gate goto out; 856*7c478bd9Sstevel@tonic-gate } 857*7c478bd9Sstevel@tonic-gate /* 858*7c478bd9Sstevel@tonic-gate * Check if we have stored a previous message block because a window 859*7c478bd9Sstevel@tonic-gate * update was split over TCP segments. If so, append the new one to 860*7c478bd9Sstevel@tonic-gate * the stored one and process the stored one as if it just arrived. 861*7c478bd9Sstevel@tonic-gate */ 862*7c478bd9Sstevel@tonic-gate if (rmip->wndw_sz_hd_mp != NULL) { 863*7c478bd9Sstevel@tonic-gate linkb(rmip->wndw_sz_hd_mp, mp); 864*7c478bd9Sstevel@tonic-gate mp = rmip->wndw_sz_hd_mp; 865*7c478bd9Sstevel@tonic-gate rmip->wndw_sz_hd_mp = NULL; 866*7c478bd9Sstevel@tonic-gate } 867*7c478bd9Sstevel@tonic-gate newmp = mp; 868*7c478bd9Sstevel@tonic-gate 869*7c478bd9Sstevel@tonic-gate while (mp) { 870*7c478bd9Sstevel@tonic-gate tmp = mp->b_rptr; 871*7c478bd9Sstevel@tonic-gate /* 872*7c478bd9Sstevel@tonic-gate * scan through the entire message block 873*7c478bd9Sstevel@tonic-gate */ 874*7c478bd9Sstevel@tonic-gate while (tmp < mp->b_wptr) { 875*7c478bd9Sstevel@tonic-gate /* 876*7c478bd9Sstevel@tonic-gate * check for FF (rlogin magic escape sequence) 877*7c478bd9Sstevel@tonic-gate */ 878*7c478bd9Sstevel@tonic-gate if (tmp[0] == RLOGIN_MAGIC) { 879*7c478bd9Sstevel@tonic-gate /* 880*7c478bd9Sstevel@tonic-gate * Update bytes read so far. 881*7c478bd9Sstevel@tonic-gate */ 882*7c478bd9Sstevel@tonic-gate count = newcount + tmp - mp->b_rptr; 883*7c478bd9Sstevel@tonic-gate /* 884*7c478bd9Sstevel@tonic-gate * Pull together message chain in case 885*7c478bd9Sstevel@tonic-gate * window escape is split across blocks. 886*7c478bd9Sstevel@tonic-gate */ 887*7c478bd9Sstevel@tonic-gate if ((pullupmsg(newmp, -1)) == 0) { 888*7c478bd9Sstevel@tonic-gate sz = msgdsize(newmp); 889*7c478bd9Sstevel@tonic-gate recover(q, newmp, sz); 890*7c478bd9Sstevel@tonic-gate return (NULL); 891*7c478bd9Sstevel@tonic-gate } 892*7c478bd9Sstevel@tonic-gate /* 893*7c478bd9Sstevel@tonic-gate * pullupmsg results in newmp consuming 894*7c478bd9Sstevel@tonic-gate * all message blocks in this chain, and 895*7c478bd9Sstevel@tonic-gate * therefor mp wants updating. 896*7c478bd9Sstevel@tonic-gate */ 897*7c478bd9Sstevel@tonic-gate mp = newmp; 898*7c478bd9Sstevel@tonic-gate 899*7c478bd9Sstevel@tonic-gate /* 900*7c478bd9Sstevel@tonic-gate * adjust tmp to where we 901*7c478bd9Sstevel@tonic-gate * stopped - count keeps track 902*7c478bd9Sstevel@tonic-gate * of bytes read so far. 903*7c478bd9Sstevel@tonic-gate * reset newcount = 0. 904*7c478bd9Sstevel@tonic-gate */ 905*7c478bd9Sstevel@tonic-gate tmp = mp->b_rptr + count; 906*7c478bd9Sstevel@tonic-gate newcount = 0; 907*7c478bd9Sstevel@tonic-gate 908*7c478bd9Sstevel@tonic-gate /* 909*7c478bd9Sstevel@tonic-gate * Use the variable tmp1 to compute where 910*7c478bd9Sstevel@tonic-gate * the end of the window escape (currently 911*7c478bd9Sstevel@tonic-gate * the only rlogin protocol sequence), then 912*7c478bd9Sstevel@tonic-gate * check to see if we got all those bytes. 913*7c478bd9Sstevel@tonic-gate */ 914*7c478bd9Sstevel@tonic-gate tmp1 = tmp + 4 + sizeof (struct winsize); 915*7c478bd9Sstevel@tonic-gate 916*7c478bd9Sstevel@tonic-gate if (tmp1 > mp->b_wptr) { 917*7c478bd9Sstevel@tonic-gate /* 918*7c478bd9Sstevel@tonic-gate * All the window escape bytes aren't 919*7c478bd9Sstevel@tonic-gate * in this TCP segment. Store this 920*7c478bd9Sstevel@tonic-gate * mblk to one side so we can append 921*7c478bd9Sstevel@tonic-gate * the rest of the escape to it when 922*7c478bd9Sstevel@tonic-gate * its segment arrives. 923*7c478bd9Sstevel@tonic-gate */ 924*7c478bd9Sstevel@tonic-gate rmip->wndw_sz_hd_mp = mp; 925*7c478bd9Sstevel@tonic-gate return (TRUE); 926*7c478bd9Sstevel@tonic-gate } 927*7c478bd9Sstevel@tonic-gate /* 928*7c478bd9Sstevel@tonic-gate * check for FF FF s s pattern 929*7c478bd9Sstevel@tonic-gate */ 930*7c478bd9Sstevel@tonic-gate if ((tmp[1] == RLOGIN_MAGIC) && 931*7c478bd9Sstevel@tonic-gate (tmp[2] == 's') && (tmp[3] == 's')) { 932*7c478bd9Sstevel@tonic-gate 933*7c478bd9Sstevel@tonic-gate /* 934*7c478bd9Sstevel@tonic-gate * If rlwinsetup returns an error, 935*7c478bd9Sstevel@tonic-gate * we do recover with newmp which 936*7c478bd9Sstevel@tonic-gate * points to new chain of mblks after 937*7c478bd9Sstevel@tonic-gate * doing window control ioctls. 938*7c478bd9Sstevel@tonic-gate * rlwinsetup returns newmp which 939*7c478bd9Sstevel@tonic-gate * contains only data part. 940*7c478bd9Sstevel@tonic-gate * Note that buried inside rlwinsetup 941*7c478bd9Sstevel@tonic-gate * is where we do the putnext. 942*7c478bd9Sstevel@tonic-gate */ 943*7c478bd9Sstevel@tonic-gate if (rlwinsetup(q, mp, tmp) == NULL) { 944*7c478bd9Sstevel@tonic-gate sz = msgdsize(mp); 945*7c478bd9Sstevel@tonic-gate recover(q, mp, sz); 946*7c478bd9Sstevel@tonic-gate return (NULL); 947*7c478bd9Sstevel@tonic-gate } 948*7c478bd9Sstevel@tonic-gate /* 949*7c478bd9Sstevel@tonic-gate * We have successfully consumed the 950*7c478bd9Sstevel@tonic-gate * window sequence, but rlwinsetup() 951*7c478bd9Sstevel@tonic-gate * and its children have moved memory 952*7c478bd9Sstevel@tonic-gate * up underneath us. This means that 953*7c478bd9Sstevel@tonic-gate * the byte underneath *tmp has not 954*7c478bd9Sstevel@tonic-gate * been scanned now. We will now need 955*7c478bd9Sstevel@tonic-gate * to rescan it. 956*7c478bd9Sstevel@tonic-gate */ 957*7c478bd9Sstevel@tonic-gate continue; 958*7c478bd9Sstevel@tonic-gate } 959*7c478bd9Sstevel@tonic-gate } 960*7c478bd9Sstevel@tonic-gate tmp++; 961*7c478bd9Sstevel@tonic-gate } 962*7c478bd9Sstevel@tonic-gate /* 963*7c478bd9Sstevel@tonic-gate * bump newcount to include size of this particular block. 964*7c478bd9Sstevel@tonic-gate */ 965*7c478bd9Sstevel@tonic-gate newcount += (mp->b_wptr - mp->b_rptr); 966*7c478bd9Sstevel@tonic-gate mp = mp->b_cont; 967*7c478bd9Sstevel@tonic-gate } 968*7c478bd9Sstevel@tonic-gate /* 969*7c478bd9Sstevel@tonic-gate * If we trimmed the message down to nothing to forward, don't 970*7c478bd9Sstevel@tonic-gate * send any M_DATA message. (Don't want to send EOF!) 971*7c478bd9Sstevel@tonic-gate */ 972*7c478bd9Sstevel@tonic-gate if (msgdsize(newmp) == 0) { 973*7c478bd9Sstevel@tonic-gate freemsg(newmp); 974*7c478bd9Sstevel@tonic-gate newmp = NULL; 975*7c478bd9Sstevel@tonic-gate } 976*7c478bd9Sstevel@tonic-gate out: 977*7c478bd9Sstevel@tonic-gate if (newmp) { 978*7c478bd9Sstevel@tonic-gate if (!canputnext(q)) { 979*7c478bd9Sstevel@tonic-gate (void) putbq(q, newmp); 980*7c478bd9Sstevel@tonic-gate return (NULL); 981*7c478bd9Sstevel@tonic-gate } else { 982*7c478bd9Sstevel@tonic-gate putnext(q, newmp); 983*7c478bd9Sstevel@tonic-gate } 984*7c478bd9Sstevel@tonic-gate } 985*7c478bd9Sstevel@tonic-gate return (TRUE); 986*7c478bd9Sstevel@tonic-gate } 987*7c478bd9Sstevel@tonic-gate 988*7c478bd9Sstevel@tonic-gate 989*7c478bd9Sstevel@tonic-gate /* 990*7c478bd9Sstevel@tonic-gate * This routine is called to handle window size changes. 991*7c478bd9Sstevel@tonic-gate * The routine returns 1 on success and 0 on error (allocb failure). 992*7c478bd9Sstevel@tonic-gate */ 993*7c478bd9Sstevel@tonic-gate static int 994*7c478bd9Sstevel@tonic-gate rlwinctl(queue_t *q, mblk_t *mp) 995*7c478bd9Sstevel@tonic-gate { 996*7c478bd9Sstevel@tonic-gate mblk_t *rl_msgp; 997*7c478bd9Sstevel@tonic-gate struct iocblk *iocbp; 998*7c478bd9Sstevel@tonic-gate struct rlmod_info *rmip = (struct rlmod_info *)q->q_ptr; 999*7c478bd9Sstevel@tonic-gate 1000*7c478bd9Sstevel@tonic-gate TRACE_2(TR_FAC_RLOGINP, TR_RLOGINP_WINCTL_IN, "rlwinctl start: q %p, " 1001*7c478bd9Sstevel@tonic-gate "mp %p", q, mp); 1002*7c478bd9Sstevel@tonic-gate 1003*7c478bd9Sstevel@tonic-gate rmip->oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */ 1004*7c478bd9Sstevel@tonic-gate 1005*7c478bd9Sstevel@tonic-gate if ((rl_msgp = mkiocb(TIOCSWINSZ)) == NULL) { 1006*7c478bd9Sstevel@tonic-gate TRACE_2(TR_FAC_RLOGINP, TR_RLOGINP_WINCTL_OUT, "rlwinctl end: " 1007*7c478bd9Sstevel@tonic-gate "q %p, mp %p, allocb failed", q, mp); 1008*7c478bd9Sstevel@tonic-gate return (0); 1009*7c478bd9Sstevel@tonic-gate } 1010*7c478bd9Sstevel@tonic-gate 1011*7c478bd9Sstevel@tonic-gate /* 1012*7c478bd9Sstevel@tonic-gate * create an M_IOCTL message type. 1013*7c478bd9Sstevel@tonic-gate */ 1014*7c478bd9Sstevel@tonic-gate rl_msgp->b_cont = mp; 1015*7c478bd9Sstevel@tonic-gate iocbp = (struct iocblk *)rl_msgp->b_rptr; 1016*7c478bd9Sstevel@tonic-gate iocbp->ioc_count = msgdsize(mp); 1017*7c478bd9Sstevel@tonic-gate 1018*7c478bd9Sstevel@tonic-gate putnext(q, rl_msgp); 1019*7c478bd9Sstevel@tonic-gate TRACE_2(TR_FAC_RLOGINP, TR_RLOGINP_WINCTL_OUT, "rlwinctl end: " 1020*7c478bd9Sstevel@tonic-gate "q %p, mp %p, done", q, mp); 1021*7c478bd9Sstevel@tonic-gate return (1); 1022*7c478bd9Sstevel@tonic-gate } 1023*7c478bd9Sstevel@tonic-gate 1024*7c478bd9Sstevel@tonic-gate /* 1025*7c478bd9Sstevel@tonic-gate * This routine sets up window size change protocol. 1026*7c478bd9Sstevel@tonic-gate * The routine returns the new mblk after issuing rlwinctl 1027*7c478bd9Sstevel@tonic-gate * for window size changes. New mblk contains only data part 1028*7c478bd9Sstevel@tonic-gate * of the message block. The routine returns 0 on error. 1029*7c478bd9Sstevel@tonic-gate */ 1030*7c478bd9Sstevel@tonic-gate static mblk_t * 1031*7c478bd9Sstevel@tonic-gate rlwinsetup(queue_t *q, mblk_t *mp, unsigned char *blk) 1032*7c478bd9Sstevel@tonic-gate { 1033*7c478bd9Sstevel@tonic-gate mblk_t *mp1; 1034*7c478bd9Sstevel@tonic-gate unsigned char *jmpmp; 1035*7c478bd9Sstevel@tonic-gate ssize_t left = 0; 1036*7c478bd9Sstevel@tonic-gate struct winsize win; 1037*7c478bd9Sstevel@tonic-gate 1038*7c478bd9Sstevel@tonic-gate /* 1039*7c478bd9Sstevel@tonic-gate * Set jmpmp to where to jump, to get just past the end of the 1040*7c478bd9Sstevel@tonic-gate * window size protocol sequence. 1041*7c478bd9Sstevel@tonic-gate */ 1042*7c478bd9Sstevel@tonic-gate jmpmp = (blk + 4 + sizeof (struct winsize)); 1043*7c478bd9Sstevel@tonic-gate left = mp->b_wptr - jmpmp; 1044*7c478bd9Sstevel@tonic-gate 1045*7c478bd9Sstevel@tonic-gate if ((mp1 = allocb(sizeof (struct winsize), BPRI_MED)) == NULL) 1046*7c478bd9Sstevel@tonic-gate return (0); 1047*7c478bd9Sstevel@tonic-gate mp1->b_datap->db_type = M_DATA; 1048*7c478bd9Sstevel@tonic-gate mp1->b_wptr = mp1->b_rptr + sizeof (struct winsize); 1049*7c478bd9Sstevel@tonic-gate bcopy(blk + 4, &win, sizeof (struct winsize)); 1050*7c478bd9Sstevel@tonic-gate win.ws_row = ntohs(win.ws_row); 1051*7c478bd9Sstevel@tonic-gate win.ws_col = ntohs(win.ws_col); 1052*7c478bd9Sstevel@tonic-gate win.ws_xpixel = ntohs(win.ws_xpixel); 1053*7c478bd9Sstevel@tonic-gate win.ws_ypixel = ntohs(win.ws_ypixel); 1054*7c478bd9Sstevel@tonic-gate bcopy(&win, mp1->b_rptr, sizeof (struct winsize)); 1055*7c478bd9Sstevel@tonic-gate 1056*7c478bd9Sstevel@tonic-gate if ((rlwinctl(q, mp1)) == NULL) { 1057*7c478bd9Sstevel@tonic-gate freeb(mp1); 1058*7c478bd9Sstevel@tonic-gate return (0); 1059*7c478bd9Sstevel@tonic-gate } 1060*7c478bd9Sstevel@tonic-gate if (left > 0) { 1061*7c478bd9Sstevel@tonic-gate /* 1062*7c478bd9Sstevel@tonic-gate * Must delete the window size protocol sequence. We do 1063*7c478bd9Sstevel@tonic-gate * this by sliding all the stuff after the sequence (jmpmp) 1064*7c478bd9Sstevel@tonic-gate * to where the sequence itself began (blk). 1065*7c478bd9Sstevel@tonic-gate */ 1066*7c478bd9Sstevel@tonic-gate bcopy(jmpmp, blk, left); 1067*7c478bd9Sstevel@tonic-gate mp->b_wptr = blk + left; 1068*7c478bd9Sstevel@tonic-gate } else 1069*7c478bd9Sstevel@tonic-gate mp->b_wptr = blk; 1070*7c478bd9Sstevel@tonic-gate return (mp); 1071*7c478bd9Sstevel@tonic-gate } 1072*7c478bd9Sstevel@tonic-gate 1073*7c478bd9Sstevel@tonic-gate /* 1074*7c478bd9Sstevel@tonic-gate * When an ioctl changes software flow control on the tty, we must notify 1075*7c478bd9Sstevel@tonic-gate * the rlogin client, so it can adjust its behavior appropriately. This 1076*7c478bd9Sstevel@tonic-gate * routine, called from either the put or service routine, determines if 1077*7c478bd9Sstevel@tonic-gate * the flow handling has changed. If so, it tries to send the indication 1078*7c478bd9Sstevel@tonic-gate * to the client. It returns true or false depending upon whether the 1079*7c478bd9Sstevel@tonic-gate * message was fully processed. If it wasn't fully processed it queues 1080*7c478bd9Sstevel@tonic-gate * the message for retry later when resources 1081*7c478bd9Sstevel@tonic-gate * (allocb/canputnext) are available. 1082*7c478bd9Sstevel@tonic-gate */ 1083*7c478bd9Sstevel@tonic-gate static boolean_t 1084*7c478bd9Sstevel@tonic-gate tty_flow(queue_t *q, struct rlmod_info *rmip, mblk_t *mp) 1085*7c478bd9Sstevel@tonic-gate { 1086*7c478bd9Sstevel@tonic-gate struct iocblk *ioc; 1087*7c478bd9Sstevel@tonic-gate struct termios *tp; 1088*7c478bd9Sstevel@tonic-gate struct termio *ti; 1089*7c478bd9Sstevel@tonic-gate int stop, ixon; 1090*7c478bd9Sstevel@tonic-gate mblk_t *tmpmp; 1091*7c478bd9Sstevel@tonic-gate char cntl; 1092*7c478bd9Sstevel@tonic-gate int error; 1093*7c478bd9Sstevel@tonic-gate 1094*7c478bd9Sstevel@tonic-gate ioc = (struct iocblk *)mp->b_rptr; 1095*7c478bd9Sstevel@tonic-gate switch (ioc->ioc_cmd) { 1096*7c478bd9Sstevel@tonic-gate 1097*7c478bd9Sstevel@tonic-gate /* 1098*7c478bd9Sstevel@tonic-gate * If it is a tty ioctl, save the output flow 1099*7c478bd9Sstevel@tonic-gate * control flag and the start and stop flow control 1100*7c478bd9Sstevel@tonic-gate * characters if they are available. 1101*7c478bd9Sstevel@tonic-gate */ 1102*7c478bd9Sstevel@tonic-gate case TCSETS: 1103*7c478bd9Sstevel@tonic-gate case TCSETSW: 1104*7c478bd9Sstevel@tonic-gate case TCSETSF: 1105*7c478bd9Sstevel@tonic-gate error = miocpullup(mp, sizeof (struct termios)); 1106*7c478bd9Sstevel@tonic-gate if (error != 0) { 1107*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, error); 1108*7c478bd9Sstevel@tonic-gate return (B_TRUE); 1109*7c478bd9Sstevel@tonic-gate } 1110*7c478bd9Sstevel@tonic-gate tp = (struct termios *)(mp->b_cont->b_rptr); 1111*7c478bd9Sstevel@tonic-gate rmip->stopc = tp->c_cc[VSTOP]; 1112*7c478bd9Sstevel@tonic-gate rmip->startc = tp->c_cc[VSTART]; 1113*7c478bd9Sstevel@tonic-gate ixon = tp->c_iflag & IXON; 1114*7c478bd9Sstevel@tonic-gate break; 1115*7c478bd9Sstevel@tonic-gate 1116*7c478bd9Sstevel@tonic-gate case TCSETA: 1117*7c478bd9Sstevel@tonic-gate case TCSETAW: 1118*7c478bd9Sstevel@tonic-gate case TCSETAF: 1119*7c478bd9Sstevel@tonic-gate error = miocpullup(mp, sizeof (struct termio)); 1120*7c478bd9Sstevel@tonic-gate if (error != 0) { 1121*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, error); 1122*7c478bd9Sstevel@tonic-gate return (B_TRUE); 1123*7c478bd9Sstevel@tonic-gate } 1124*7c478bd9Sstevel@tonic-gate ti = (struct termio *)(mp->b_cont->b_rptr); 1125*7c478bd9Sstevel@tonic-gate ixon = ti->c_iflag & IXON; 1126*7c478bd9Sstevel@tonic-gate break; 1127*7c478bd9Sstevel@tonic-gate 1128*7c478bd9Sstevel@tonic-gate default: 1129*7c478bd9Sstevel@tonic-gate /* 1130*7c478bd9Sstevel@tonic-gate * This function must never be called for an M_IOCTL 1131*7c478bd9Sstevel@tonic-gate * except the listed ones. 1132*7c478bd9Sstevel@tonic-gate */ 1133*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 1134*7c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, 1135*7c478bd9Sstevel@tonic-gate "rloginmod: tty_flow: bad ioctl 0x%x", ioc->ioc_cmd); 1136*7c478bd9Sstevel@tonic-gate #else 1137*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EINVAL); 1138*7c478bd9Sstevel@tonic-gate return (B_TRUE); 1139*7c478bd9Sstevel@tonic-gate #endif 1140*7c478bd9Sstevel@tonic-gate } 1141*7c478bd9Sstevel@tonic-gate /* 1142*7c478bd9Sstevel@tonic-gate * If tty ioctl processing is done, check for stopmode 1143*7c478bd9Sstevel@tonic-gate */ 1144*7c478bd9Sstevel@tonic-gate stop = (ixon && (rmip->stopc == CTRL('s')) && 1145*7c478bd9Sstevel@tonic-gate (rmip->startc == CTRL('q'))); 1146*7c478bd9Sstevel@tonic-gate if (rmip->stopmode == TIOCPKT_NOSTOP) { 1147*7c478bd9Sstevel@tonic-gate if (stop) { 1148*7c478bd9Sstevel@tonic-gate cntl = rmip->oobdata[0] | TIOCPKT_DOSTOP; 1149*7c478bd9Sstevel@tonic-gate if ((tmpmp = make_expmblk(cntl)) == NULL) { 1150*7c478bd9Sstevel@tonic-gate recover(q, mp, sizeof (mblk_t)); 1151*7c478bd9Sstevel@tonic-gate return (B_FALSE); 1152*7c478bd9Sstevel@tonic-gate } 1153*7c478bd9Sstevel@tonic-gate if (!canputnext(q)) { 1154*7c478bd9Sstevel@tonic-gate freemsg(tmpmp); 1155*7c478bd9Sstevel@tonic-gate return (B_FALSE); 1156*7c478bd9Sstevel@tonic-gate } 1157*7c478bd9Sstevel@tonic-gate putnext(q, tmpmp); 1158*7c478bd9Sstevel@tonic-gate rmip->stopmode = TIOCPKT_DOSTOP; 1159*7c478bd9Sstevel@tonic-gate } 1160*7c478bd9Sstevel@tonic-gate } else { 1161*7c478bd9Sstevel@tonic-gate if (!stop) { 1162*7c478bd9Sstevel@tonic-gate cntl = rmip->oobdata[0] | TIOCPKT_NOSTOP; 1163*7c478bd9Sstevel@tonic-gate if ((tmpmp = make_expmblk(cntl)) == NULL) { 1164*7c478bd9Sstevel@tonic-gate recover(q, mp, sizeof (mblk_t)); 1165*7c478bd9Sstevel@tonic-gate return (B_FALSE); 1166*7c478bd9Sstevel@tonic-gate } 1167*7c478bd9Sstevel@tonic-gate if (!canputnext(q)) { 1168*7c478bd9Sstevel@tonic-gate freemsg(tmpmp); 1169*7c478bd9Sstevel@tonic-gate return (B_FALSE); 1170*7c478bd9Sstevel@tonic-gate } 1171*7c478bd9Sstevel@tonic-gate putnext(q, tmpmp); 1172*7c478bd9Sstevel@tonic-gate rmip->stopmode = TIOCPKT_NOSTOP; 1173*7c478bd9Sstevel@tonic-gate } 1174*7c478bd9Sstevel@tonic-gate } 1175*7c478bd9Sstevel@tonic-gate 1176*7c478bd9Sstevel@tonic-gate miocack(q, mp, 0, 0); 1177*7c478bd9Sstevel@tonic-gate return (B_TRUE); 1178*7c478bd9Sstevel@tonic-gate } 1179*7c478bd9Sstevel@tonic-gate 1180*7c478bd9Sstevel@tonic-gate /* rlmodwioctl - handle M_IOCTL messages on the write queue. */ 1181*7c478bd9Sstevel@tonic-gate 1182*7c478bd9Sstevel@tonic-gate static boolean_t 1183*7c478bd9Sstevel@tonic-gate rlmodwioctl(queue_t *q, mblk_t *mp) 1184*7c478bd9Sstevel@tonic-gate { 1185*7c478bd9Sstevel@tonic-gate struct iocblk *ioc; 1186*7c478bd9Sstevel@tonic-gate struct rlmod_info *rmip = (struct rlmod_info *)q->q_ptr; 1187*7c478bd9Sstevel@tonic-gate int error; 1188*7c478bd9Sstevel@tonic-gate 1189*7c478bd9Sstevel@tonic-gate ioc = (struct iocblk *)mp->b_rptr; 1190*7c478bd9Sstevel@tonic-gate switch (ioc->ioc_cmd) { 1191*7c478bd9Sstevel@tonic-gate 1192*7c478bd9Sstevel@tonic-gate /* 1193*7c478bd9Sstevel@tonic-gate * This is a special ioctl to reenable the queue. 1194*7c478bd9Sstevel@tonic-gate * The initial data read from the stream head is 1195*7c478bd9Sstevel@tonic-gate * put back on the queue. 1196*7c478bd9Sstevel@tonic-gate */ 1197*7c478bd9Sstevel@tonic-gate case RL_IOC_ENABLE: 1198*7c478bd9Sstevel@tonic-gate /* 1199*7c478bd9Sstevel@tonic-gate * Send negative ack if RL_DISABLED flag is not set 1200*7c478bd9Sstevel@tonic-gate */ 1201*7c478bd9Sstevel@tonic-gate 1202*7c478bd9Sstevel@tonic-gate if (!(rmip->flags & RL_DISABLED)) { 1203*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EINVAL); 1204*7c478bd9Sstevel@tonic-gate break; 1205*7c478bd9Sstevel@tonic-gate } 1206*7c478bd9Sstevel@tonic-gate if (mp->b_cont) { 1207*7c478bd9Sstevel@tonic-gate (void) putbq(RD(q), mp->b_cont); 1208*7c478bd9Sstevel@tonic-gate mp->b_cont = NULL; 1209*7c478bd9Sstevel@tonic-gate } 1210*7c478bd9Sstevel@tonic-gate 1211*7c478bd9Sstevel@tonic-gate if (rmip->flags & RL_DISABLED) 1212*7c478bd9Sstevel@tonic-gate rmip->flags &= ~RL_DISABLED; 1213*7c478bd9Sstevel@tonic-gate qenable(RD(q)); 1214*7c478bd9Sstevel@tonic-gate miocack(q, mp, 0, 0); 1215*7c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_WPUT_OUT, 1216*7c478bd9Sstevel@tonic-gate "rlmodwput end: q %p, mp %p, %s", 1217*7c478bd9Sstevel@tonic-gate q, mp, "IOCACK enable"); 1218*7c478bd9Sstevel@tonic-gate return (B_TRUE); 1219*7c478bd9Sstevel@tonic-gate 1220*7c478bd9Sstevel@tonic-gate /* 1221*7c478bd9Sstevel@tonic-gate * If it is a tty ioctl, save the output flow 1222*7c478bd9Sstevel@tonic-gate * control flag and the start and stop flow control 1223*7c478bd9Sstevel@tonic-gate * characters if they are available. 1224*7c478bd9Sstevel@tonic-gate */ 1225*7c478bd9Sstevel@tonic-gate case TCSETS: 1226*7c478bd9Sstevel@tonic-gate case TCSETSW: 1227*7c478bd9Sstevel@tonic-gate case TCSETSF: 1228*7c478bd9Sstevel@tonic-gate case TCSETA: 1229*7c478bd9Sstevel@tonic-gate case TCSETAW: 1230*7c478bd9Sstevel@tonic-gate case TCSETAF: 1231*7c478bd9Sstevel@tonic-gate return (tty_flow(q, rmip, mp)); 1232*7c478bd9Sstevel@tonic-gate 1233*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 1234*7c478bd9Sstevel@tonic-gate case TIOCSWINSZ: 1235*7c478bd9Sstevel@tonic-gate case TIOCSTI: 1236*7c478bd9Sstevel@tonic-gate case TCSBRK: 1237*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EINVAL); 1238*7c478bd9Sstevel@tonic-gate break; 1239*7c478bd9Sstevel@tonic-gate #endif 1240*7c478bd9Sstevel@tonic-gate case CRYPTPASSTHRU: 1241*7c478bd9Sstevel@tonic-gate error = miocpullup(mp, sizeof (uchar_t)); 1242*7c478bd9Sstevel@tonic-gate if (error != 0) { 1243*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, error); 1244*7c478bd9Sstevel@tonic-gate break; 1245*7c478bd9Sstevel@tonic-gate } 1246*7c478bd9Sstevel@tonic-gate if (*(mp->b_cont->b_rptr) == 0x01) 1247*7c478bd9Sstevel@tonic-gate rmip->flags |= RL_IOCPASSTHRU; 1248*7c478bd9Sstevel@tonic-gate else 1249*7c478bd9Sstevel@tonic-gate rmip->flags &= ~RL_IOCPASSTHRU; 1250*7c478bd9Sstevel@tonic-gate 1251*7c478bd9Sstevel@tonic-gate miocack(q, mp, NULL, 0); 1252*7c478bd9Sstevel@tonic-gate break; 1253*7c478bd9Sstevel@tonic-gate 1254*7c478bd9Sstevel@tonic-gate default: 1255*7c478bd9Sstevel@tonic-gate if (rmip->flags & RL_IOCPASSTHRU) { 1256*7c478bd9Sstevel@tonic-gate putnext(q, mp); 1257*7c478bd9Sstevel@tonic-gate } else { 1258*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 1259*7c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, 1260*7c478bd9Sstevel@tonic-gate "rlmodwioctl: unexpected ioctl type 0x%x", 1261*7c478bd9Sstevel@tonic-gate ioc->ioc_cmd); 1262*7c478bd9Sstevel@tonic-gate #endif 1263*7c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EINVAL); 1264*7c478bd9Sstevel@tonic-gate } 1265*7c478bd9Sstevel@tonic-gate } 1266*7c478bd9Sstevel@tonic-gate return (B_TRUE); 1267*7c478bd9Sstevel@tonic-gate } 1268*7c478bd9Sstevel@tonic-gate 1269*7c478bd9Sstevel@tonic-gate static void 1270*7c478bd9Sstevel@tonic-gate rlmod_timer(void *arg) 1271*7c478bd9Sstevel@tonic-gate { 1272*7c478bd9Sstevel@tonic-gate queue_t *q = arg; 1273*7c478bd9Sstevel@tonic-gate struct rlmod_info *rmip = (struct rlmod_info *)q->q_ptr; 1274*7c478bd9Sstevel@tonic-gate 1275*7c478bd9Sstevel@tonic-gate ASSERT(rmip); 1276*7c478bd9Sstevel@tonic-gate if (q->q_flag & QREADR) { 1277*7c478bd9Sstevel@tonic-gate ASSERT(rmip->rtimoutid); 1278*7c478bd9Sstevel@tonic-gate rmip->rtimoutid = 0; 1279*7c478bd9Sstevel@tonic-gate } else { 1280*7c478bd9Sstevel@tonic-gate ASSERT(rmip->wtimoutid); 1281*7c478bd9Sstevel@tonic-gate rmip->wtimoutid = 0; 1282*7c478bd9Sstevel@tonic-gate } 1283*7c478bd9Sstevel@tonic-gate enableok(q); 1284*7c478bd9Sstevel@tonic-gate qenable(q); 1285*7c478bd9Sstevel@tonic-gate } 1286*7c478bd9Sstevel@tonic-gate 1287*7c478bd9Sstevel@tonic-gate static void 1288*7c478bd9Sstevel@tonic-gate rlmod_buffer(void *arg) 1289*7c478bd9Sstevel@tonic-gate { 1290*7c478bd9Sstevel@tonic-gate queue_t *q = arg; 1291*7c478bd9Sstevel@tonic-gate struct rlmod_info *rmip = (struct rlmod_info *)q->q_ptr; 1292*7c478bd9Sstevel@tonic-gate 1293*7c478bd9Sstevel@tonic-gate ASSERT(rmip); 1294*7c478bd9Sstevel@tonic-gate if (q->q_flag & QREADR) { 1295*7c478bd9Sstevel@tonic-gate ASSERT(rmip->rbufcid); 1296*7c478bd9Sstevel@tonic-gate rmip->rbufcid = 0; 1297*7c478bd9Sstevel@tonic-gate } else { 1298*7c478bd9Sstevel@tonic-gate ASSERT(rmip->wbufcid); 1299*7c478bd9Sstevel@tonic-gate rmip->wbufcid = 0; 1300*7c478bd9Sstevel@tonic-gate } 1301*7c478bd9Sstevel@tonic-gate enableok(q); 1302*7c478bd9Sstevel@tonic-gate qenable(q); 1303*7c478bd9Sstevel@tonic-gate } 1304*7c478bd9Sstevel@tonic-gate 1305*7c478bd9Sstevel@tonic-gate static void 1306*7c478bd9Sstevel@tonic-gate recover(queue_t *q, mblk_t *mp, size_t size) 1307*7c478bd9Sstevel@tonic-gate { 1308*7c478bd9Sstevel@tonic-gate /* 1309*7c478bd9Sstevel@tonic-gate * Avoid re-enabling the queue. 1310*7c478bd9Sstevel@tonic-gate */ 1311*7c478bd9Sstevel@tonic-gate ASSERT(mp->b_datap->db_type < QPCTL); 1312*7c478bd9Sstevel@tonic-gate 1313*7c478bd9Sstevel@tonic-gate noenable(q); 1314*7c478bd9Sstevel@tonic-gate (void) putbq(q, mp); 1315*7c478bd9Sstevel@tonic-gate recover1(q, size); 1316*7c478bd9Sstevel@tonic-gate } 1317*7c478bd9Sstevel@tonic-gate 1318*7c478bd9Sstevel@tonic-gate static void 1319*7c478bd9Sstevel@tonic-gate recover1(queue_t *q, size_t size) 1320*7c478bd9Sstevel@tonic-gate { 1321*7c478bd9Sstevel@tonic-gate struct rlmod_info *rmip = (struct rlmod_info *)q->q_ptr; 1322*7c478bd9Sstevel@tonic-gate timeout_id_t tid; 1323*7c478bd9Sstevel@tonic-gate bufcall_id_t bid; 1324*7c478bd9Sstevel@tonic-gate 1325*7c478bd9Sstevel@tonic-gate /* 1326*7c478bd9Sstevel@tonic-gate * Make sure there is at most one outstanding request per queue. 1327*7c478bd9Sstevel@tonic-gate */ 1328*7c478bd9Sstevel@tonic-gate if (q->q_flag & QREADR) { 1329*7c478bd9Sstevel@tonic-gate if (rmip->rtimoutid || rmip->rbufcid) 1330*7c478bd9Sstevel@tonic-gate return; 1331*7c478bd9Sstevel@tonic-gate } else { 1332*7c478bd9Sstevel@tonic-gate if (rmip->wtimoutid || rmip->wbufcid) 1333*7c478bd9Sstevel@tonic-gate return; 1334*7c478bd9Sstevel@tonic-gate } 1335*7c478bd9Sstevel@tonic-gate if (!(bid = qbufcall(RD(q), size, BPRI_MED, rlmod_buffer, q))) { 1336*7c478bd9Sstevel@tonic-gate tid = qtimeout(RD(q), rlmod_timer, q, SIMWAIT); 1337*7c478bd9Sstevel@tonic-gate if (q->q_flag & QREADR) 1338*7c478bd9Sstevel@tonic-gate rmip->rtimoutid = tid; 1339*7c478bd9Sstevel@tonic-gate else 1340*7c478bd9Sstevel@tonic-gate rmip->wtimoutid = tid; 1341*7c478bd9Sstevel@tonic-gate } else { 1342*7c478bd9Sstevel@tonic-gate if (q->q_flag & QREADR) 1343*7c478bd9Sstevel@tonic-gate rmip->rbufcid = bid; 1344*7c478bd9Sstevel@tonic-gate else 1345*7c478bd9Sstevel@tonic-gate rmip->wbufcid = bid; 1346*7c478bd9Sstevel@tonic-gate } 1347*7c478bd9Sstevel@tonic-gate } 1348