17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate * with the License.
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate * and limitations under the License.
137c478bd9Sstevel@tonic-gate *
147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * CDDL HEADER END
217c478bd9Sstevel@tonic-gate */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
2548bbca81SDaniel Hoffman * Copyright (c) 2016 by Delphix. All rights reserved.
267c478bd9Sstevel@tonic-gate */
277c478bd9Sstevel@tonic-gate
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate * This module implements the services provided by the rlogin daemon
307c478bd9Sstevel@tonic-gate * after the connection is set up. Mainly this means responding to
317c478bd9Sstevel@tonic-gate * interrupts and window size changes. It begins operation in "disabled"
327c478bd9Sstevel@tonic-gate * state, and sends a T_DATA_REQ to the daemon to indicate that it is
337c478bd9Sstevel@tonic-gate * in place and ready to be enabled. The daemon can then know when all
347c478bd9Sstevel@tonic-gate * data which sneaked passed rlmod (before it was pushed) has been received.
357c478bd9Sstevel@tonic-gate * The daemon may process this data, or send data back to be inserted in
367c478bd9Sstevel@tonic-gate * the read queue at the head with the RL_IOC_ENABLE ioctl.
377c478bd9Sstevel@tonic-gate */
387c478bd9Sstevel@tonic-gate
397c478bd9Sstevel@tonic-gate #include <sys/types.h>
407c478bd9Sstevel@tonic-gate #include <sys/param.h>
417c478bd9Sstevel@tonic-gate #include <sys/stream.h>
427c478bd9Sstevel@tonic-gate #include <sys/stropts.h>
437c478bd9Sstevel@tonic-gate #include <sys/strsun.h>
447c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
457c478bd9Sstevel@tonic-gate #include <sys/errno.h>
467c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
477c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
487c478bd9Sstevel@tonic-gate #include <sys/tihdr.h>
497c478bd9Sstevel@tonic-gate #include <sys/ptem.h>
507c478bd9Sstevel@tonic-gate #include <sys/conf.h>
517c478bd9Sstevel@tonic-gate #include <sys/debug.h>
527c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
537c478bd9Sstevel@tonic-gate #include <sys/vtrace.h>
547c478bd9Sstevel@tonic-gate #include <sys/rlioctl.h>
557c478bd9Sstevel@tonic-gate #include <sys/termios.h>
567c478bd9Sstevel@tonic-gate #include <sys/termio.h>
577c478bd9Sstevel@tonic-gate #include <sys/byteorder.h>
587c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
597c478bd9Sstevel@tonic-gate #include <sys/cryptmod.h>
607c478bd9Sstevel@tonic-gate
617c478bd9Sstevel@tonic-gate extern struct streamtab rloginmodinfo;
627c478bd9Sstevel@tonic-gate
637c478bd9Sstevel@tonic-gate static struct fmodsw fsw = {
647c478bd9Sstevel@tonic-gate "rlmod",
657c478bd9Sstevel@tonic-gate &rloginmodinfo,
667c478bd9Sstevel@tonic-gate D_MTQPAIR | D_MP
677c478bd9Sstevel@tonic-gate };
687c478bd9Sstevel@tonic-gate
697c478bd9Sstevel@tonic-gate /*
707c478bd9Sstevel@tonic-gate * Module linkage information for the kernel.
717c478bd9Sstevel@tonic-gate */
727c478bd9Sstevel@tonic-gate
737c478bd9Sstevel@tonic-gate static struct modlstrmod modlstrmod = {
747c478bd9Sstevel@tonic-gate &mod_strmodops,
757c478bd9Sstevel@tonic-gate "rloginmod module",
767c478bd9Sstevel@tonic-gate &fsw
777c478bd9Sstevel@tonic-gate };
787c478bd9Sstevel@tonic-gate
797c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
807c478bd9Sstevel@tonic-gate MODREV_1, &modlstrmod, NULL
817c478bd9Sstevel@tonic-gate };
827c478bd9Sstevel@tonic-gate
837c478bd9Sstevel@tonic-gate
847c478bd9Sstevel@tonic-gate int
_init(void)857c478bd9Sstevel@tonic-gate _init(void)
867c478bd9Sstevel@tonic-gate {
877c478bd9Sstevel@tonic-gate return (mod_install(&modlinkage));
887c478bd9Sstevel@tonic-gate }
897c478bd9Sstevel@tonic-gate
907c478bd9Sstevel@tonic-gate int
_fini(void)917c478bd9Sstevel@tonic-gate _fini(void)
927c478bd9Sstevel@tonic-gate {
937c478bd9Sstevel@tonic-gate return (mod_remove(&modlinkage));
947c478bd9Sstevel@tonic-gate }
957c478bd9Sstevel@tonic-gate
967c478bd9Sstevel@tonic-gate int
_info(struct modinfo * modinfop)977c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
987c478bd9Sstevel@tonic-gate {
997c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop));
1007c478bd9Sstevel@tonic-gate }
1017c478bd9Sstevel@tonic-gate
1027c478bd9Sstevel@tonic-gate struct rlmod_info; /* forward reference for function prototype */
1037c478bd9Sstevel@tonic-gate
1047c478bd9Sstevel@tonic-gate static int rlmodopen(queue_t *, dev_t *, int, int, cred_t *);
1057c478bd9Sstevel@tonic-gate static int rlmodclose(queue_t *, int, cred_t *);
1067c478bd9Sstevel@tonic-gate static int rlmodrput(queue_t *, mblk_t *);
1077c478bd9Sstevel@tonic-gate static int rlmodrsrv(queue_t *);
1087c478bd9Sstevel@tonic-gate static int rlmodwput(queue_t *, mblk_t *);
1097c478bd9Sstevel@tonic-gate static int rlmodwsrv(queue_t *);
1107c478bd9Sstevel@tonic-gate static int rlmodrmsg(queue_t *, mblk_t *);
1117c478bd9Sstevel@tonic-gate static mblk_t *make_expmblk(char);
112*a8eee26aSToomas Soome static int rlwinctl(queue_t *, mblk_t *);
1137c478bd9Sstevel@tonic-gate static mblk_t *rlwinsetup(queue_t *, mblk_t *, unsigned char *);
1147c478bd9Sstevel@tonic-gate
1157c478bd9Sstevel@tonic-gate static void rlmod_timer(void *);
1167c478bd9Sstevel@tonic-gate static void rlmod_buffer(void *);
1177c478bd9Sstevel@tonic-gate static boolean_t tty_flow(queue_t *, struct rlmod_info *, mblk_t *);
1187c478bd9Sstevel@tonic-gate static boolean_t rlmodwioctl(queue_t *, mblk_t *);
1197c478bd9Sstevel@tonic-gate static void recover(queue_t *, mblk_t *, size_t);
1207c478bd9Sstevel@tonic-gate static void recover1(queue_t *, size_t);
1217c478bd9Sstevel@tonic-gate
1227c478bd9Sstevel@tonic-gate #define RLMOD_ID 106
1237c478bd9Sstevel@tonic-gate #define SIMWAIT (1*hz)
1247c478bd9Sstevel@tonic-gate
1257c478bd9Sstevel@tonic-gate /*
1267c478bd9Sstevel@tonic-gate * Stream module data structure definitions.
1277c478bd9Sstevel@tonic-gate * generally pushed onto tcp by rlogin daemon
1287c478bd9Sstevel@tonic-gate *
1297c478bd9Sstevel@tonic-gate */
1307c478bd9Sstevel@tonic-gate static struct module_info rloginmodiinfo = {
1317c478bd9Sstevel@tonic-gate RLMOD_ID, /* module id number */
1327c478bd9Sstevel@tonic-gate "rlmod", /* module name */
1337c478bd9Sstevel@tonic-gate 0, /* minimum packet size */
1347c478bd9Sstevel@tonic-gate INFPSZ, /* maximum packet size */
1357c478bd9Sstevel@tonic-gate 512, /* hi-water mark */
1367c478bd9Sstevel@tonic-gate 256 /* lo-water mark */
1377c478bd9Sstevel@tonic-gate };
1387c478bd9Sstevel@tonic-gate
1397c478bd9Sstevel@tonic-gate static struct qinit rloginmodrinit = {
1407c478bd9Sstevel@tonic-gate rlmodrput,
1417c478bd9Sstevel@tonic-gate rlmodrsrv,
1427c478bd9Sstevel@tonic-gate rlmodopen,
1437c478bd9Sstevel@tonic-gate rlmodclose,
1447c478bd9Sstevel@tonic-gate nulldev,
1457c478bd9Sstevel@tonic-gate &rloginmodiinfo,
1467c478bd9Sstevel@tonic-gate NULL
1477c478bd9Sstevel@tonic-gate };
1487c478bd9Sstevel@tonic-gate
1497c478bd9Sstevel@tonic-gate static struct qinit rloginmodwinit = {
1507c478bd9Sstevel@tonic-gate rlmodwput,
1517c478bd9Sstevel@tonic-gate rlmodwsrv,
1527c478bd9Sstevel@tonic-gate NULL,
1537c478bd9Sstevel@tonic-gate NULL,
1547c478bd9Sstevel@tonic-gate nulldev,
1557c478bd9Sstevel@tonic-gate &rloginmodiinfo,
1567c478bd9Sstevel@tonic-gate NULL
1577c478bd9Sstevel@tonic-gate };
1587c478bd9Sstevel@tonic-gate
1597c478bd9Sstevel@tonic-gate struct streamtab rloginmodinfo = {
1607c478bd9Sstevel@tonic-gate &rloginmodrinit,
1617c478bd9Sstevel@tonic-gate &rloginmodwinit,
1627c478bd9Sstevel@tonic-gate NULL,
1637c478bd9Sstevel@tonic-gate NULL
1647c478bd9Sstevel@tonic-gate };
1657c478bd9Sstevel@tonic-gate
1667c478bd9Sstevel@tonic-gate /*
1677c478bd9Sstevel@tonic-gate * Per-instance state struct for the rloginmod module.
1687c478bd9Sstevel@tonic-gate */
1697c478bd9Sstevel@tonic-gate struct rlmod_info
1707c478bd9Sstevel@tonic-gate {
1717c478bd9Sstevel@tonic-gate int flags;
1727c478bd9Sstevel@tonic-gate bufcall_id_t wbufcid;
1737c478bd9Sstevel@tonic-gate bufcall_id_t rbufcid;
1747c478bd9Sstevel@tonic-gate timeout_id_t wtimoutid;
1757c478bd9Sstevel@tonic-gate timeout_id_t rtimoutid;
1767c478bd9Sstevel@tonic-gate int rl_expdat;
1777c478bd9Sstevel@tonic-gate int stopmode;
1787c478bd9Sstevel@tonic-gate mblk_t *unbind_mp;
1797c478bd9Sstevel@tonic-gate char startc;
1807c478bd9Sstevel@tonic-gate char stopc;
1817c478bd9Sstevel@tonic-gate char oobdata[1];
1827c478bd9Sstevel@tonic-gate mblk_t *wndw_sz_hd_mp;
1837c478bd9Sstevel@tonic-gate };
1847c478bd9Sstevel@tonic-gate
1857c478bd9Sstevel@tonic-gate /*
1867c478bd9Sstevel@tonic-gate * Flag used in flags
1877c478bd9Sstevel@tonic-gate */
1887c478bd9Sstevel@tonic-gate #define RL_DISABLED 0x1
1897c478bd9Sstevel@tonic-gate #define RL_IOCPASSTHRU 0x2
1907c478bd9Sstevel@tonic-gate
1917c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1927c478bd9Sstevel@tonic-gate static void
dummy_callback(void * arg)1937c478bd9Sstevel@tonic-gate dummy_callback(void *arg)
1947c478bd9Sstevel@tonic-gate {}
1957c478bd9Sstevel@tonic-gate
1967c478bd9Sstevel@tonic-gate /*
1977c478bd9Sstevel@tonic-gate * rlmodopen - open routine gets called when the
1987c478bd9Sstevel@tonic-gate * module gets pushed onto the stream.
1997c478bd9Sstevel@tonic-gate */
2007c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2017c478bd9Sstevel@tonic-gate static int
rlmodopen(queue_t * q,dev_t * devp,int oflag,int sflag,cred_t * cred)2027c478bd9Sstevel@tonic-gate rlmodopen(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *cred)
2037c478bd9Sstevel@tonic-gate {
2047c478bd9Sstevel@tonic-gate struct rlmod_info *rmip;
2057c478bd9Sstevel@tonic-gate union T_primitives *tp;
2067c478bd9Sstevel@tonic-gate mblk_t *bp;
2077c478bd9Sstevel@tonic-gate int error;
2087c478bd9Sstevel@tonic-gate
2097c478bd9Sstevel@tonic-gate if (sflag != MODOPEN)
2107c478bd9Sstevel@tonic-gate return (EINVAL);
2117c478bd9Sstevel@tonic-gate
2127c478bd9Sstevel@tonic-gate if (q->q_ptr != NULL) {
2137c478bd9Sstevel@tonic-gate /* It's already attached. */
2147c478bd9Sstevel@tonic-gate return (0);
2157c478bd9Sstevel@tonic-gate }
2167c478bd9Sstevel@tonic-gate
2177c478bd9Sstevel@tonic-gate /*
2187c478bd9Sstevel@tonic-gate * Allocate state structure.
2197c478bd9Sstevel@tonic-gate */
2207c478bd9Sstevel@tonic-gate rmip = kmem_zalloc(sizeof (*rmip), KM_SLEEP);
2217c478bd9Sstevel@tonic-gate
2227c478bd9Sstevel@tonic-gate /*
2237c478bd9Sstevel@tonic-gate * Cross-link.
2247c478bd9Sstevel@tonic-gate */
2257c478bd9Sstevel@tonic-gate q->q_ptr = rmip;
2267c478bd9Sstevel@tonic-gate WR(q)->q_ptr = rmip;
2277c478bd9Sstevel@tonic-gate rmip->rl_expdat = 0;
2287c478bd9Sstevel@tonic-gate rmip->stopmode = TIOCPKT_DOSTOP;
2297c478bd9Sstevel@tonic-gate rmip->startc = CTRL('q');
2307c478bd9Sstevel@tonic-gate rmip->stopc = CTRL('s');
2317c478bd9Sstevel@tonic-gate rmip->oobdata[0] = (char)TIOCPKT_WINDOW;
2327c478bd9Sstevel@tonic-gate rmip->wndw_sz_hd_mp = NULL;
2337c478bd9Sstevel@tonic-gate /*
2347c478bd9Sstevel@tonic-gate * Allow only non-M_DATA blocks to pass up to in.rlogind until
2357c478bd9Sstevel@tonic-gate * it is ready for M_DATA (indicated by RL_IOC_ENABLE).
2367c478bd9Sstevel@tonic-gate */
2377c478bd9Sstevel@tonic-gate rmip->flags |= RL_DISABLED;
2387c478bd9Sstevel@tonic-gate
2397c478bd9Sstevel@tonic-gate qprocson(q);
2407c478bd9Sstevel@tonic-gate
2417c478bd9Sstevel@tonic-gate /*
2427c478bd9Sstevel@tonic-gate * Since TCP operates in the TLI-inspired brain-dead fashion,
2437c478bd9Sstevel@tonic-gate * the connection will revert to bound state if the connection
2447c478bd9Sstevel@tonic-gate * is reset by the client. We must send a T_UNBIND_REQ in
2457c478bd9Sstevel@tonic-gate * that case so the port doesn't get "wedged" (preventing
2467c478bd9Sstevel@tonic-gate * inetd from being able to restart the listener). Allocate
2477c478bd9Sstevel@tonic-gate * it here, so that we don't need to worry about allocb()
2487c478bd9Sstevel@tonic-gate * failures later.
2497c478bd9Sstevel@tonic-gate */
2507c478bd9Sstevel@tonic-gate while ((rmip->unbind_mp = allocb(sizeof (union T_primitives),
2517c478bd9Sstevel@tonic-gate BPRI_HI)) == NULL) {
2527c478bd9Sstevel@tonic-gate bufcall_id_t id = qbufcall(q, sizeof (union T_primitives),
2537c478bd9Sstevel@tonic-gate BPRI_HI, dummy_callback, NULL);
2547c478bd9Sstevel@tonic-gate if (!qwait_sig(q)) {
2557c478bd9Sstevel@tonic-gate qunbufcall(q, id);
2567c478bd9Sstevel@tonic-gate error = EINTR;
2577c478bd9Sstevel@tonic-gate goto fail;
2587c478bd9Sstevel@tonic-gate }
2597c478bd9Sstevel@tonic-gate qunbufcall(q, id);
2607c478bd9Sstevel@tonic-gate }
2617c478bd9Sstevel@tonic-gate rmip->unbind_mp->b_wptr = rmip->unbind_mp->b_rptr +
2627c478bd9Sstevel@tonic-gate sizeof (struct T_unbind_req);
2637c478bd9Sstevel@tonic-gate rmip->unbind_mp->b_datap->db_type = M_PROTO;
2647c478bd9Sstevel@tonic-gate tp = (union T_primitives *)rmip->unbind_mp->b_rptr;
2657c478bd9Sstevel@tonic-gate tp->type = T_UNBIND_REQ;
2667c478bd9Sstevel@tonic-gate
2677c478bd9Sstevel@tonic-gate /*
2687c478bd9Sstevel@tonic-gate * Send a M_PROTO msg of type T_DATA_REQ (this is unique for
2697c478bd9Sstevel@tonic-gate * read queue since only write queue can get T_DATA_REQ).
2707c478bd9Sstevel@tonic-gate * Readstream routine in the daemon will do a getmsg() till
2717c478bd9Sstevel@tonic-gate * it receives this proto message.
2727c478bd9Sstevel@tonic-gate */
2737c478bd9Sstevel@tonic-gate while ((bp = allocb(sizeof (union T_primitives), BPRI_HI)) == NULL) {
2747c478bd9Sstevel@tonic-gate bufcall_id_t id = qbufcall(q, sizeof (union T_primitives),
2757c478bd9Sstevel@tonic-gate BPRI_HI, dummy_callback, NULL);
2767c478bd9Sstevel@tonic-gate if (!qwait_sig(q)) {
2777c478bd9Sstevel@tonic-gate qunbufcall(q, id);
2787c478bd9Sstevel@tonic-gate error = EINTR;
2797c478bd9Sstevel@tonic-gate goto fail;
2807c478bd9Sstevel@tonic-gate }
2817c478bd9Sstevel@tonic-gate qunbufcall(q, id);
2827c478bd9Sstevel@tonic-gate }
2837c478bd9Sstevel@tonic-gate bp->b_datap->db_type = M_PROTO;
2847c478bd9Sstevel@tonic-gate bp->b_wptr = bp->b_rptr + sizeof (union T_primitives);
2857c478bd9Sstevel@tonic-gate tp = (union T_primitives *)bp->b_rptr;
2867c478bd9Sstevel@tonic-gate tp->type = T_DATA_REQ;
2877c478bd9Sstevel@tonic-gate tp->data_req.MORE_flag = 0;
2887c478bd9Sstevel@tonic-gate
2897c478bd9Sstevel@tonic-gate putnext(q, bp);
2907c478bd9Sstevel@tonic-gate return (0);
2917c478bd9Sstevel@tonic-gate fail:
2927c478bd9Sstevel@tonic-gate qprocsoff(q);
2937c478bd9Sstevel@tonic-gate if (rmip->unbind_mp != NULL) {
2947c478bd9Sstevel@tonic-gate freemsg(rmip->unbind_mp);
2957c478bd9Sstevel@tonic-gate }
2967c478bd9Sstevel@tonic-gate kmem_free(rmip, sizeof (struct rlmod_info));
2977c478bd9Sstevel@tonic-gate q->q_ptr = NULL;
2987c478bd9Sstevel@tonic-gate WR(q)->q_ptr = NULL;
2997c478bd9Sstevel@tonic-gate return (error);
3007c478bd9Sstevel@tonic-gate }
3017c478bd9Sstevel@tonic-gate
3027c478bd9Sstevel@tonic-gate
3037c478bd9Sstevel@tonic-gate /*
3047c478bd9Sstevel@tonic-gate * rlmodclose - This routine gets called when the module
3057c478bd9Sstevel@tonic-gate * gets popped off of the stream.
3067c478bd9Sstevel@tonic-gate */
3077c478bd9Sstevel@tonic-gate
3087c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3097c478bd9Sstevel@tonic-gate static int
rlmodclose(queue_t * q,int flag,cred_t * credp)3107c478bd9Sstevel@tonic-gate rlmodclose(queue_t *q, int flag, cred_t *credp)
3117c478bd9Sstevel@tonic-gate {
3127c478bd9Sstevel@tonic-gate struct rlmod_info *rmip = (struct rlmod_info *)q->q_ptr;
3137c478bd9Sstevel@tonic-gate mblk_t *mp;
3147c478bd9Sstevel@tonic-gate
3157c478bd9Sstevel@tonic-gate /*
3167c478bd9Sstevel@tonic-gate * Flush any write-side data downstream. Ignoring flow
3177c478bd9Sstevel@tonic-gate * control at this point is known to be safe because the
3187c478bd9Sstevel@tonic-gate * M_HANGUP below poisons the stream such that no modules can
3197c478bd9Sstevel@tonic-gate * be pushed again.
3207c478bd9Sstevel@tonic-gate */
3217c478bd9Sstevel@tonic-gate while (mp = getq(WR(q)))
3227c478bd9Sstevel@tonic-gate putnext(WR(q), mp);
3237c478bd9Sstevel@tonic-gate
3247c478bd9Sstevel@tonic-gate /* Poison the stream head so that we can't be pushed again. */
3257c478bd9Sstevel@tonic-gate (void) putnextctl(q, M_HANGUP);
3267c478bd9Sstevel@tonic-gate
3277c478bd9Sstevel@tonic-gate qprocsoff(q);
3287c478bd9Sstevel@tonic-gate if (rmip->wbufcid) {
3297c478bd9Sstevel@tonic-gate qunbufcall(q, rmip->wbufcid);
3307c478bd9Sstevel@tonic-gate rmip->wbufcid = 0;
3317c478bd9Sstevel@tonic-gate }
3327c478bd9Sstevel@tonic-gate if (rmip->rbufcid) {
3337c478bd9Sstevel@tonic-gate qunbufcall(q, rmip->rbufcid);
3347c478bd9Sstevel@tonic-gate rmip->rbufcid = 0;
3357c478bd9Sstevel@tonic-gate }
3367c478bd9Sstevel@tonic-gate if (rmip->wtimoutid) {
3377c478bd9Sstevel@tonic-gate (void) quntimeout(q, rmip->wtimoutid);
3387c478bd9Sstevel@tonic-gate rmip->wtimoutid = 0;
3397c478bd9Sstevel@tonic-gate }
3407c478bd9Sstevel@tonic-gate if (rmip->rtimoutid) {
3417c478bd9Sstevel@tonic-gate (void) quntimeout(q, rmip->rtimoutid);
3427c478bd9Sstevel@tonic-gate rmip->rtimoutid = 0;
3437c478bd9Sstevel@tonic-gate }
3447c478bd9Sstevel@tonic-gate
3457c478bd9Sstevel@tonic-gate if (rmip->unbind_mp != NULL) {
3467c478bd9Sstevel@tonic-gate freemsg(rmip->unbind_mp);
3477c478bd9Sstevel@tonic-gate }
3487c478bd9Sstevel@tonic-gate
3497c478bd9Sstevel@tonic-gate if (rmip->wndw_sz_hd_mp != NULL) {
3507c478bd9Sstevel@tonic-gate freemsg(rmip->wndw_sz_hd_mp);
3517c478bd9Sstevel@tonic-gate }
3527c478bd9Sstevel@tonic-gate
3537c478bd9Sstevel@tonic-gate kmem_free(q->q_ptr, sizeof (struct rlmod_info));
3547c478bd9Sstevel@tonic-gate q->q_ptr = WR(q)->q_ptr = NULL;
3557c478bd9Sstevel@tonic-gate return (0);
3567c478bd9Sstevel@tonic-gate }
3577c478bd9Sstevel@tonic-gate
3587c478bd9Sstevel@tonic-gate /*
3597c478bd9Sstevel@tonic-gate * rlmodrput - Module read queue put procedure.
3607c478bd9Sstevel@tonic-gate * This is called from the module or
3617c478bd9Sstevel@tonic-gate * driver downstream.
3627c478bd9Sstevel@tonic-gate */
3637c478bd9Sstevel@tonic-gate
3647c478bd9Sstevel@tonic-gate static int
rlmodrput(queue_t * q,mblk_t * mp)3657c478bd9Sstevel@tonic-gate rlmodrput(queue_t *q, mblk_t *mp)
3667c478bd9Sstevel@tonic-gate {
3677c478bd9Sstevel@tonic-gate struct rlmod_info *rmip = (struct rlmod_info *)q->q_ptr;
3687c478bd9Sstevel@tonic-gate union T_primitives *tip;
3697c478bd9Sstevel@tonic-gate
3707c478bd9Sstevel@tonic-gate TRACE_2(TR_FAC_RLOGINP, TR_RLOGINP_RPUT_IN, "rlmodrput start: "
3717c478bd9Sstevel@tonic-gate "q %p, mp %p", q, mp);
3727c478bd9Sstevel@tonic-gate
3737c478bd9Sstevel@tonic-gate
3747c478bd9Sstevel@tonic-gate /* if low (normal) priority... */
3757c478bd9Sstevel@tonic-gate if ((mp->b_datap->db_type < QPCTL) &&
3767c478bd9Sstevel@tonic-gate /* ...and data is already queued... */
3777c478bd9Sstevel@tonic-gate ((q->q_first) ||
378*a8eee26aSToomas Soome /* ...or currently disabled and this is M_DATA... */
379*a8eee26aSToomas Soome ((rmip->flags & RL_DISABLED) &&
380*a8eee26aSToomas Soome (mp->b_datap->db_type == M_DATA)))) {
3817c478bd9Sstevel@tonic-gate /* ...delay delivery of the message */
3827c478bd9Sstevel@tonic-gate (void) putq(q, mp);
3837c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_RPUT_OUT,
3847c478bd9Sstevel@tonic-gate "rlmodrput end: q %p, mp %p, %s", q, mp, "flow");
3857c478bd9Sstevel@tonic-gate return (0);
3867c478bd9Sstevel@tonic-gate }
3877c478bd9Sstevel@tonic-gate
3887c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) {
3897c478bd9Sstevel@tonic-gate
3907c478bd9Sstevel@tonic-gate case M_PROTO:
3917c478bd9Sstevel@tonic-gate case M_PCPROTO:
3927c478bd9Sstevel@tonic-gate tip = (union T_primitives *)mp->b_rptr;
3937c478bd9Sstevel@tonic-gate switch (tip->type) {
3947c478bd9Sstevel@tonic-gate
3957c478bd9Sstevel@tonic-gate case T_ORDREL_IND:
3967c478bd9Sstevel@tonic-gate case T_DISCON_IND:
3977c478bd9Sstevel@tonic-gate /* Make into M_HANGUP and putnext */
3987c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_HANGUP;
3997c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr;
4007c478bd9Sstevel@tonic-gate if (mp->b_cont) {
4017c478bd9Sstevel@tonic-gate freemsg(mp->b_cont);
4027c478bd9Sstevel@tonic-gate mp->b_cont = NULL;
4037c478bd9Sstevel@tonic-gate }
4047c478bd9Sstevel@tonic-gate /*
4057c478bd9Sstevel@tonic-gate * If we haven't already, send T_UNBIND_REQ to prevent
4067c478bd9Sstevel@tonic-gate * TCP from going into "BOUND" state and locking up the
4077c478bd9Sstevel@tonic-gate * port.
4087c478bd9Sstevel@tonic-gate */
4097c478bd9Sstevel@tonic-gate if (tip->type == T_DISCON_IND && rmip->unbind_mp !=
4107c478bd9Sstevel@tonic-gate NULL) {
4117c478bd9Sstevel@tonic-gate putnext(q, mp);
4127c478bd9Sstevel@tonic-gate qreply(q, rmip->unbind_mp);
4137c478bd9Sstevel@tonic-gate rmip->unbind_mp = NULL;
4147c478bd9Sstevel@tonic-gate } else {
4157c478bd9Sstevel@tonic-gate putnext(q, mp);
4167c478bd9Sstevel@tonic-gate }
4177c478bd9Sstevel@tonic-gate break;
4187c478bd9Sstevel@tonic-gate
4197c478bd9Sstevel@tonic-gate /*
4207c478bd9Sstevel@tonic-gate * We only get T_OK_ACK when we issue the unbind, and it can
4217c478bd9Sstevel@tonic-gate * be ignored safely.
4227c478bd9Sstevel@tonic-gate */
4237c478bd9Sstevel@tonic-gate case T_OK_ACK:
4247c478bd9Sstevel@tonic-gate ASSERT(rmip->unbind_mp == NULL);
4257c478bd9Sstevel@tonic-gate freemsg(mp);
4267c478bd9Sstevel@tonic-gate break;
4277c478bd9Sstevel@tonic-gate
4287c478bd9Sstevel@tonic-gate default:
4297c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE,
4307c478bd9Sstevel@tonic-gate "rlmodrput: got 0x%x type M_PROTO/M_PCPROTO msg",
4317c478bd9Sstevel@tonic-gate tip->type);
4327c478bd9Sstevel@tonic-gate freemsg(mp);
4337c478bd9Sstevel@tonic-gate }
4347c478bd9Sstevel@tonic-gate break;
4357c478bd9Sstevel@tonic-gate
4367c478bd9Sstevel@tonic-gate case M_DATA:
4377c478bd9Sstevel@tonic-gate if (canputnext(q) && q->q_first == NULL) {
4387c478bd9Sstevel@tonic-gate (void) rlmodrmsg(q, mp);
4397c478bd9Sstevel@tonic-gate } else {
4407c478bd9Sstevel@tonic-gate (void) putq(q, mp);
4417c478bd9Sstevel@tonic-gate }
4427c478bd9Sstevel@tonic-gate break;
4437c478bd9Sstevel@tonic-gate
4447c478bd9Sstevel@tonic-gate case M_FLUSH:
4457c478bd9Sstevel@tonic-gate /*
4467c478bd9Sstevel@tonic-gate * Since M_FLUSH came from TCP, we mark it bound for
4477c478bd9Sstevel@tonic-gate * daemon, not tty. This only happens when TCP expects
4487c478bd9Sstevel@tonic-gate * to do a connection reset.
4497c478bd9Sstevel@tonic-gate */
4507c478bd9Sstevel@tonic-gate mp->b_flag |= MSGMARK;
4517c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHR)
4527c478bd9Sstevel@tonic-gate flushq(q, FLUSHALL);
4537c478bd9Sstevel@tonic-gate
4547c478bd9Sstevel@tonic-gate putnext(q, mp);
4557c478bd9Sstevel@tonic-gate break;
4567c478bd9Sstevel@tonic-gate
4577c478bd9Sstevel@tonic-gate case M_PCSIG:
4587c478bd9Sstevel@tonic-gate case M_ERROR:
4597c478bd9Sstevel@tonic-gate case M_IOCACK:
4607c478bd9Sstevel@tonic-gate case M_IOCNAK:
4617c478bd9Sstevel@tonic-gate case M_SETOPTS:
4627c478bd9Sstevel@tonic-gate if (mp->b_datap->db_type <= QPCTL && !canputnext(q))
4637c478bd9Sstevel@tonic-gate (void) putq(q, mp);
4647c478bd9Sstevel@tonic-gate else
4657c478bd9Sstevel@tonic-gate putnext(q, mp);
4667c478bd9Sstevel@tonic-gate break;
4677c478bd9Sstevel@tonic-gate
4687c478bd9Sstevel@tonic-gate default:
4697c478bd9Sstevel@tonic-gate #ifdef DEBUG
4707c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "rlmodrput: unexpected msg type 0x%x",
4717c478bd9Sstevel@tonic-gate mp->b_datap->db_type);
4727c478bd9Sstevel@tonic-gate #endif
4737c478bd9Sstevel@tonic-gate freemsg(mp);
4747c478bd9Sstevel@tonic-gate }
4757c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_RPUT_OUT, "rlmodrput end: q %p, "
476*a8eee26aSToomas Soome "mp %p, %s", q, mp, "done");
4777c478bd9Sstevel@tonic-gate return (0);
4787c478bd9Sstevel@tonic-gate }
4797c478bd9Sstevel@tonic-gate
4807c478bd9Sstevel@tonic-gate /*
4817c478bd9Sstevel@tonic-gate * rlmodrsrv - module read service procedure
4827c478bd9Sstevel@tonic-gate */
4837c478bd9Sstevel@tonic-gate static int
rlmodrsrv(queue_t * q)4847c478bd9Sstevel@tonic-gate rlmodrsrv(queue_t *q)
4857c478bd9Sstevel@tonic-gate {
4867c478bd9Sstevel@tonic-gate mblk_t *mp;
4877c478bd9Sstevel@tonic-gate struct rlmod_info *rmip = (struct rlmod_info *)q->q_ptr;
4887c478bd9Sstevel@tonic-gate union T_primitives *tip;
4897c478bd9Sstevel@tonic-gate
4907c478bd9Sstevel@tonic-gate TRACE_1(TR_FAC_RLOGINP, TR_RLOGINP_RSRV_IN, "rlmodrsrv start: "
4917c478bd9Sstevel@tonic-gate "q %p", q);
4927c478bd9Sstevel@tonic-gate while ((mp = getq(q)) != NULL) {
4937c478bd9Sstevel@tonic-gate
4947c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) {
4957c478bd9Sstevel@tonic-gate case M_DATA:
4967c478bd9Sstevel@tonic-gate if (rmip->flags & RL_DISABLED) {
4977c478bd9Sstevel@tonic-gate (void) putbq(q, mp);
4987c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_RSRV_OUT,
499*a8eee26aSToomas Soome "rlmodrsrv end: q %p, mp %p, %s", q, mp,
500*a8eee26aSToomas Soome "disabled");
5017c478bd9Sstevel@tonic-gate return (0);
5027c478bd9Sstevel@tonic-gate }
5037c478bd9Sstevel@tonic-gate if (!canputnext(q)) {
5047c478bd9Sstevel@tonic-gate (void) putbq(q, mp);
5057c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_RSRV_OUT,
5067c478bd9Sstevel@tonic-gate "rlmodrsrv end: q %p, mp %p, %s",
5077c478bd9Sstevel@tonic-gate q, mp, "!canputnext");
5087c478bd9Sstevel@tonic-gate return (0);
5097c478bd9Sstevel@tonic-gate }
5107c478bd9Sstevel@tonic-gate if (!rlmodrmsg(q, mp)) {
5117c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_RSRV_OUT,
5127c478bd9Sstevel@tonic-gate "rlmodrsrv end: q %p, mp %p, %s",
5137c478bd9Sstevel@tonic-gate q, mp, "!rlmodrmsg");
5147c478bd9Sstevel@tonic-gate return (0);
5157c478bd9Sstevel@tonic-gate }
5167c478bd9Sstevel@tonic-gate break;
5177c478bd9Sstevel@tonic-gate
5187c478bd9Sstevel@tonic-gate case M_PROTO:
5197c478bd9Sstevel@tonic-gate tip = (union T_primitives *)mp->b_rptr;
5207c478bd9Sstevel@tonic-gate switch (tip->type) {
5217c478bd9Sstevel@tonic-gate
5227c478bd9Sstevel@tonic-gate case T_ORDREL_IND:
5237c478bd9Sstevel@tonic-gate case T_DISCON_IND:
5247c478bd9Sstevel@tonic-gate /* Make into M_HANGUP and putnext */
5257c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_HANGUP;
5267c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr;
5277c478bd9Sstevel@tonic-gate if (mp->b_cont) {
5287c478bd9Sstevel@tonic-gate freemsg(mp->b_cont);
5297c478bd9Sstevel@tonic-gate mp->b_cont = NULL;
5307c478bd9Sstevel@tonic-gate }
5317c478bd9Sstevel@tonic-gate /*
5327c478bd9Sstevel@tonic-gate * If we haven't already, send T_UNBIND_REQ
5337c478bd9Sstevel@tonic-gate * to prevent TCP from going into "BOUND"
5347c478bd9Sstevel@tonic-gate * state and locking up the port.
5357c478bd9Sstevel@tonic-gate */
5367c478bd9Sstevel@tonic-gate if (tip->type == T_DISCON_IND &&
5377c478bd9Sstevel@tonic-gate rmip->unbind_mp != NULL) {
5387c478bd9Sstevel@tonic-gate putnext(q, mp);
5397c478bd9Sstevel@tonic-gate qreply(q, rmip->unbind_mp);
5407c478bd9Sstevel@tonic-gate rmip->unbind_mp = NULL;
5417c478bd9Sstevel@tonic-gate } else {
5427c478bd9Sstevel@tonic-gate putnext(q, mp);
5437c478bd9Sstevel@tonic-gate }
5447c478bd9Sstevel@tonic-gate break;
5457c478bd9Sstevel@tonic-gate
5467c478bd9Sstevel@tonic-gate /*
5477c478bd9Sstevel@tonic-gate * We only get T_OK_ACK when we issue the unbind, and
5487c478bd9Sstevel@tonic-gate * it can be ignored safely.
5497c478bd9Sstevel@tonic-gate */
5507c478bd9Sstevel@tonic-gate case T_OK_ACK:
5517c478bd9Sstevel@tonic-gate ASSERT(rmip->unbind_mp == NULL);
5527c478bd9Sstevel@tonic-gate freemsg(mp);
5537c478bd9Sstevel@tonic-gate break;
5547c478bd9Sstevel@tonic-gate
5557c478bd9Sstevel@tonic-gate default:
5567c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE,
5577c478bd9Sstevel@tonic-gate "rlmodrsrv: got 0x%x type PROTO msg",
5587c478bd9Sstevel@tonic-gate tip->type);
5597c478bd9Sstevel@tonic-gate freemsg(mp);
5607c478bd9Sstevel@tonic-gate }
5617c478bd9Sstevel@tonic-gate break;
5627c478bd9Sstevel@tonic-gate
5637c478bd9Sstevel@tonic-gate case M_SETOPTS:
5647c478bd9Sstevel@tonic-gate if (!canputnext(q)) {
5657c478bd9Sstevel@tonic-gate (void) putbq(q, mp);
5667c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_RSRV_OUT,
5677c478bd9Sstevel@tonic-gate "rlmodrsrv end: q %p, mp %p, %s",
5687c478bd9Sstevel@tonic-gate q, mp, "!canputnext M_SETOPTS");
5697c478bd9Sstevel@tonic-gate return (0);
5707c478bd9Sstevel@tonic-gate }
5717c478bd9Sstevel@tonic-gate putnext(q, mp);
5727c478bd9Sstevel@tonic-gate break;
5737c478bd9Sstevel@tonic-gate
5747c478bd9Sstevel@tonic-gate default:
5757c478bd9Sstevel@tonic-gate #ifdef DEBUG
5767c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE,
5777c478bd9Sstevel@tonic-gate "rlmodrsrv: unexpected msg type 0x%x",
5787c478bd9Sstevel@tonic-gate mp->b_datap->db_type);
5797c478bd9Sstevel@tonic-gate #endif
5807c478bd9Sstevel@tonic-gate freemsg(mp);
5817c478bd9Sstevel@tonic-gate }
5827c478bd9Sstevel@tonic-gate }
5837c478bd9Sstevel@tonic-gate
5847c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_RSRV_OUT, "rlmodrsrv end: q %p, "
5857c478bd9Sstevel@tonic-gate "mp %p, %s", q, mp, "empty");
5867c478bd9Sstevel@tonic-gate
5877c478bd9Sstevel@tonic-gate return (0);
5887c478bd9Sstevel@tonic-gate }
5897c478bd9Sstevel@tonic-gate
5907c478bd9Sstevel@tonic-gate /*
5917c478bd9Sstevel@tonic-gate * rlmodwput - Module write queue put procedure.
5927c478bd9Sstevel@tonic-gate * All non-zero messages are send downstream unchanged
5937c478bd9Sstevel@tonic-gate */
5947c478bd9Sstevel@tonic-gate static int
rlmodwput(queue_t * q,mblk_t * mp)5957c478bd9Sstevel@tonic-gate rlmodwput(queue_t *q, mblk_t *mp)
5967c478bd9Sstevel@tonic-gate {
5977c478bd9Sstevel@tonic-gate char cntl;
5987c478bd9Sstevel@tonic-gate struct rlmod_info *rmip = (struct rlmod_info *)q->q_ptr;
5997c478bd9Sstevel@tonic-gate mblk_t *tmpmp;
6007c478bd9Sstevel@tonic-gate int rw;
6017c478bd9Sstevel@tonic-gate
6027c478bd9Sstevel@tonic-gate TRACE_2(TR_FAC_RLOGINP, TR_RLOGINP_WPUT_IN, "rlmodwput start: "
6037c478bd9Sstevel@tonic-gate "q %p, mp %p", q, mp);
6047c478bd9Sstevel@tonic-gate
6057c478bd9Sstevel@tonic-gate if (rmip->rl_expdat) {
6067c478bd9Sstevel@tonic-gate /*
6077c478bd9Sstevel@tonic-gate * call make_expmblk to create an expedited
6087c478bd9Sstevel@tonic-gate * message block.
6097c478bd9Sstevel@tonic-gate */
6107c478bd9Sstevel@tonic-gate cntl = rmip->oobdata[0] | TIOCPKT_FLUSHWRITE;
6117c478bd9Sstevel@tonic-gate
6127c478bd9Sstevel@tonic-gate if (!canputnext(q)) {
6137c478bd9Sstevel@tonic-gate (void) putq(q, mp);
6147c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_WPUT_OUT,
6157c478bd9Sstevel@tonic-gate "rlmodwput end: q %p, mp %p, %s",
6167c478bd9Sstevel@tonic-gate q, mp, "expdata && !canputnext");
6177c478bd9Sstevel@tonic-gate return (0);
6187c478bd9Sstevel@tonic-gate }
6197c478bd9Sstevel@tonic-gate if ((tmpmp = make_expmblk(cntl))) {
6207c478bd9Sstevel@tonic-gate putnext(q, tmpmp);
6217c478bd9Sstevel@tonic-gate rmip->rl_expdat = 0;
6227c478bd9Sstevel@tonic-gate } else {
6237c478bd9Sstevel@tonic-gate recover1(q, sizeof (mblk_t)); /* XXX.sparker */
6247c478bd9Sstevel@tonic-gate }
6257c478bd9Sstevel@tonic-gate }
6267c478bd9Sstevel@tonic-gate
6277c478bd9Sstevel@tonic-gate if ((q->q_first || rmip->rl_expdat) && mp->b_datap->db_type < QPCTL) {
6287c478bd9Sstevel@tonic-gate (void) putq(q, mp);
6297c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_WPUT_OUT, "rlmodwput end: "
6307c478bd9Sstevel@tonic-gate "q %p, mp %p, %s", q, mp, "queued data");
6317c478bd9Sstevel@tonic-gate return (0);
6327c478bd9Sstevel@tonic-gate }
6337c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) {
6347c478bd9Sstevel@tonic-gate
6357c478bd9Sstevel@tonic-gate case M_DATA:
6367c478bd9Sstevel@tonic-gate if (!canputnext(q))
6377c478bd9Sstevel@tonic-gate (void) putq(q, mp);
6387c478bd9Sstevel@tonic-gate else
6397c478bd9Sstevel@tonic-gate putnext(q, mp);
6407c478bd9Sstevel@tonic-gate break;
6417c478bd9Sstevel@tonic-gate
6427c478bd9Sstevel@tonic-gate case M_FLUSH:
6437c478bd9Sstevel@tonic-gate /*
6447c478bd9Sstevel@tonic-gate * We must take care to create and forward out-of-band data
6457c478bd9Sstevel@tonic-gate * indicating the flush to the far side.
6467c478bd9Sstevel@tonic-gate */
6477c478bd9Sstevel@tonic-gate rw = *mp->b_rptr;
6487c478bd9Sstevel@tonic-gate *mp->b_rptr &= ~FLUSHW;
6497c478bd9Sstevel@tonic-gate qreply(q, mp);
6507c478bd9Sstevel@tonic-gate if (rw & FLUSHW) {
6517c478bd9Sstevel@tonic-gate /*
6527c478bd9Sstevel@tonic-gate * Since all rlogin protocol data is sent in this
6537c478bd9Sstevel@tonic-gate * direction as urgent data, and TCP does not flush
6547c478bd9Sstevel@tonic-gate * urgent data, it is okay to actually forward this
6557c478bd9Sstevel@tonic-gate * flush. (telmod cannot.)
6567c478bd9Sstevel@tonic-gate */
6577c478bd9Sstevel@tonic-gate flushq(q, FLUSHDATA);
6587c478bd9Sstevel@tonic-gate /*
6597c478bd9Sstevel@tonic-gate * The putnextctl1() call can only fail if we're
6607c478bd9Sstevel@tonic-gate * out of memory. Ideally, we might set a state
6617c478bd9Sstevel@tonic-gate * bit and reschedule ourselves when memory
6627c478bd9Sstevel@tonic-gate * becomes available, so we make sure not to miss
6637c478bd9Sstevel@tonic-gate * sending the FLUSHW to TCP before the urgent
6647c478bd9Sstevel@tonic-gate * byte. Not doing this just means in some cases
6657c478bd9Sstevel@tonic-gate * a bit more trash passes before the flush takes
6667c478bd9Sstevel@tonic-gate * hold.
6677c478bd9Sstevel@tonic-gate */
6687c478bd9Sstevel@tonic-gate (void) putnextctl1(q, M_FLUSH, FLUSHW);
6697c478bd9Sstevel@tonic-gate /*
6707c478bd9Sstevel@tonic-gate * Notify peer of the write flush request.
6717c478bd9Sstevel@tonic-gate */
6727c478bd9Sstevel@tonic-gate cntl = rmip->oobdata[0] | TIOCPKT_FLUSHWRITE;
6737c478bd9Sstevel@tonic-gate if (!canputnext(q)) {
6747c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_WPUT_OUT,
6757c478bd9Sstevel@tonic-gate "rlmodwput end: q %p, mp %p, %s",
6767c478bd9Sstevel@tonic-gate q, mp, "flushw && !canputnext");
6777c478bd9Sstevel@tonic-gate return (0);
6787c478bd9Sstevel@tonic-gate }
6797c478bd9Sstevel@tonic-gate if ((mp = make_expmblk(cntl)) == NULL) {
6807c478bd9Sstevel@tonic-gate rmip->rl_expdat = 1;
6817c478bd9Sstevel@tonic-gate recover1(q, sizeof (mblk_t));
6827c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_WPUT_OUT,
6837c478bd9Sstevel@tonic-gate "rlmodwput end: q %p, mp %p, %s",
6847c478bd9Sstevel@tonic-gate q, mp, "!make_expmblk");
6857c478bd9Sstevel@tonic-gate return (0);
6867c478bd9Sstevel@tonic-gate }
6877c478bd9Sstevel@tonic-gate putnext(q, mp);
6887c478bd9Sstevel@tonic-gate }
6897c478bd9Sstevel@tonic-gate break;
6907c478bd9Sstevel@tonic-gate
6917c478bd9Sstevel@tonic-gate case M_IOCTL:
6927c478bd9Sstevel@tonic-gate if (!rlmodwioctl(q, mp))
6937c478bd9Sstevel@tonic-gate (void) putq(q, mp);
6947c478bd9Sstevel@tonic-gate break;
6957c478bd9Sstevel@tonic-gate
6967c478bd9Sstevel@tonic-gate case M_PROTO:
6977c478bd9Sstevel@tonic-gate switch (((union T_primitives *)mp->b_rptr)->type) {
6987c478bd9Sstevel@tonic-gate case T_EXDATA_REQ:
6997c478bd9Sstevel@tonic-gate case T_ORDREL_REQ:
7007c478bd9Sstevel@tonic-gate case T_DISCON_REQ:
7017c478bd9Sstevel@tonic-gate putnext(q, mp);
7027c478bd9Sstevel@tonic-gate break;
7037c478bd9Sstevel@tonic-gate
7047c478bd9Sstevel@tonic-gate default:
7057c478bd9Sstevel@tonic-gate #ifdef DEBUG
7067c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE,
7077c478bd9Sstevel@tonic-gate "rlmodwput: unexpected TPI primitive 0x%x",
7087c478bd9Sstevel@tonic-gate ((union T_primitives *)mp->b_rptr)->type);
7097c478bd9Sstevel@tonic-gate #endif
7107c478bd9Sstevel@tonic-gate freemsg(mp);
7117c478bd9Sstevel@tonic-gate }
7127c478bd9Sstevel@tonic-gate break;
7137c478bd9Sstevel@tonic-gate
7147c478bd9Sstevel@tonic-gate case M_PCPROTO:
7157c478bd9Sstevel@tonic-gate if (((struct T_exdata_req *)mp->b_rptr)->PRIM_type ==
7167c478bd9Sstevel@tonic-gate T_DISCON_REQ) {
7177c478bd9Sstevel@tonic-gate putnext(q, mp);
7187c478bd9Sstevel@tonic-gate } else {
7197c478bd9Sstevel@tonic-gate /* XXX.sparker Log unexpected message */
7207c478bd9Sstevel@tonic-gate freemsg(mp);
7217c478bd9Sstevel@tonic-gate }
7227c478bd9Sstevel@tonic-gate break;
7237c478bd9Sstevel@tonic-gate
7247c478bd9Sstevel@tonic-gate default:
7257c478bd9Sstevel@tonic-gate #ifdef DEBUG
7267c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE,
7277c478bd9Sstevel@tonic-gate "rlmodwput: unexpected msg type 0x%x",
7287c478bd9Sstevel@tonic-gate mp->b_datap->db_type);
7297c478bd9Sstevel@tonic-gate #endif
7307c478bd9Sstevel@tonic-gate freemsg(mp);
7317c478bd9Sstevel@tonic-gate break;
7327c478bd9Sstevel@tonic-gate }
7337c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_WPUT_OUT, "rlmodwput end: "
7347c478bd9Sstevel@tonic-gate "q %p, mp %p, %s", q, mp, "done");
7357c478bd9Sstevel@tonic-gate return (0);
7367c478bd9Sstevel@tonic-gate }
7377c478bd9Sstevel@tonic-gate
7387c478bd9Sstevel@tonic-gate /*
7397c478bd9Sstevel@tonic-gate * rlmodwsrv - module write service procedure
7407c478bd9Sstevel@tonic-gate */
7417c478bd9Sstevel@tonic-gate static int
rlmodwsrv(queue_t * q)7427c478bd9Sstevel@tonic-gate rlmodwsrv(queue_t *q)
7437c478bd9Sstevel@tonic-gate {
7447c478bd9Sstevel@tonic-gate mblk_t *mp, *tmpmp;
7457c478bd9Sstevel@tonic-gate char cntl;
7467c478bd9Sstevel@tonic-gate struct rlmod_info *rmip = (struct rlmod_info *)q->q_ptr;
7477c478bd9Sstevel@tonic-gate
7487c478bd9Sstevel@tonic-gate TRACE_1(TR_FAC_RLOGINP, TR_RLOGINP_WSRV_IN, "rlmodwsrv "
7497c478bd9Sstevel@tonic-gate "start: q %p", q);
7507c478bd9Sstevel@tonic-gate if (rmip->rl_expdat) {
7517c478bd9Sstevel@tonic-gate /*
7527c478bd9Sstevel@tonic-gate * call make_expmblk to create an expedited
7537c478bd9Sstevel@tonic-gate * message block.
7547c478bd9Sstevel@tonic-gate */
7557c478bd9Sstevel@tonic-gate cntl = rmip->oobdata[0] | TIOCPKT_FLUSHWRITE;
7567c478bd9Sstevel@tonic-gate if (!canputnext(q)) {
7577c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_WSRV_OUT,
7587c478bd9Sstevel@tonic-gate "rlmodwsrv end: q %p, mp %p, %s",
7597c478bd9Sstevel@tonic-gate q, NULL, "!canputnext && expdat");
7607c478bd9Sstevel@tonic-gate return (0);
7617c478bd9Sstevel@tonic-gate }
7627c478bd9Sstevel@tonic-gate if ((tmpmp = make_expmblk(cntl))) {
7637c478bd9Sstevel@tonic-gate putnext(q, tmpmp);
7647c478bd9Sstevel@tonic-gate rmip->rl_expdat = 0;
7657c478bd9Sstevel@tonic-gate } else {
7667c478bd9Sstevel@tonic-gate recover1(q, sizeof (mblk_t));
7677c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_WSRV_OUT,
7687c478bd9Sstevel@tonic-gate "rlmodwsrv end: q %p, mp %p, %s",
7697c478bd9Sstevel@tonic-gate q, NULL, "!make_expmblk");
7707c478bd9Sstevel@tonic-gate return (0);
7717c478bd9Sstevel@tonic-gate }
7727c478bd9Sstevel@tonic-gate }
7737c478bd9Sstevel@tonic-gate while ((mp = getq(q)) != NULL) {
7747c478bd9Sstevel@tonic-gate
7757c478bd9Sstevel@tonic-gate if (!canputnext(q) || rmip->rl_expdat) {
7767c478bd9Sstevel@tonic-gate (void) putbq(q, mp);
7777c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_WSRV_OUT,
7787c478bd9Sstevel@tonic-gate "rlmodwsrv end: q %p, mp %p, %s",
7797c478bd9Sstevel@tonic-gate q, mp, "!canputnext || expdat");
7807c478bd9Sstevel@tonic-gate return (0);
7817c478bd9Sstevel@tonic-gate }
7827c478bd9Sstevel@tonic-gate if (mp->b_datap->db_type == M_IOCTL) {
7837c478bd9Sstevel@tonic-gate if (!rlmodwioctl(q, mp)) {
7847c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_WSRV_OUT,
7857c478bd9Sstevel@tonic-gate "rlmodwsrv end: q %p, mp %p, %s",
7867c478bd9Sstevel@tonic-gate q, mp, "!rlmodwioctl");
7877c478bd9Sstevel@tonic-gate (void) putbq(q, mp);
7887c478bd9Sstevel@tonic-gate return (0);
7897c478bd9Sstevel@tonic-gate }
7907c478bd9Sstevel@tonic-gate continue;
7917c478bd9Sstevel@tonic-gate }
7927c478bd9Sstevel@tonic-gate putnext(q, mp);
7937c478bd9Sstevel@tonic-gate }
7947c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_WSRV_OUT, "rlmodwsrv end: q %p, "
7957c478bd9Sstevel@tonic-gate "mp %p, %s", q, mp, "done");
7967c478bd9Sstevel@tonic-gate return (0);
7977c478bd9Sstevel@tonic-gate }
7987c478bd9Sstevel@tonic-gate
7997c478bd9Sstevel@tonic-gate /*
8007c478bd9Sstevel@tonic-gate * This routine returns a message block with an expedited
8017c478bd9Sstevel@tonic-gate * data request
8027c478bd9Sstevel@tonic-gate */
8037c478bd9Sstevel@tonic-gate static mblk_t *
make_expmblk(char cntl)8047c478bd9Sstevel@tonic-gate make_expmblk(char cntl)
8057c478bd9Sstevel@tonic-gate {
8067c478bd9Sstevel@tonic-gate mblk_t *mp;
8077c478bd9Sstevel@tonic-gate mblk_t *bp;
8087c478bd9Sstevel@tonic-gate struct T_exdata_req *data_req;
8097c478bd9Sstevel@tonic-gate
8107c478bd9Sstevel@tonic-gate bp = allocb(sizeof (struct T_exdata_req), BPRI_MED);
8117c478bd9Sstevel@tonic-gate if (bp == NULL)
8127c478bd9Sstevel@tonic-gate return (NULL);
8137c478bd9Sstevel@tonic-gate if ((mp = allocb(sizeof (char), BPRI_MED)) == NULL) {
8147c478bd9Sstevel@tonic-gate freeb(bp);
8157c478bd9Sstevel@tonic-gate return (NULL);
8167c478bd9Sstevel@tonic-gate }
8177c478bd9Sstevel@tonic-gate bp->b_datap->db_type = M_PROTO;
8187c478bd9Sstevel@tonic-gate data_req = (struct T_exdata_req *)bp->b_rptr;
8197c478bd9Sstevel@tonic-gate data_req->PRIM_type = T_EXDATA_REQ;
8207c478bd9Sstevel@tonic-gate data_req->MORE_flag = 0;
8217c478bd9Sstevel@tonic-gate
8227c478bd9Sstevel@tonic-gate bp->b_wptr += sizeof (struct T_exdata_req);
8237c478bd9Sstevel@tonic-gate /*
8247c478bd9Sstevel@tonic-gate * Send a 1 byte data message block with appropriate
8257c478bd9Sstevel@tonic-gate * control character.
8267c478bd9Sstevel@tonic-gate */
8277c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_DATA;
8287c478bd9Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + 1;
8297c478bd9Sstevel@tonic-gate (*(char *)(mp->b_rptr)) = cntl;
8307c478bd9Sstevel@tonic-gate bp->b_cont = mp;
8317c478bd9Sstevel@tonic-gate return (bp);
8327c478bd9Sstevel@tonic-gate }
8337c478bd9Sstevel@tonic-gate /*
8347c478bd9Sstevel@tonic-gate * This routine parses M_DATA messages checking for window size protocol
8357c478bd9Sstevel@tonic-gate * from a given message block. It returns TRUE if no resource exhaustion
8367c478bd9Sstevel@tonic-gate * conditions are found. This is for use in the service procedure, which
8377c478bd9Sstevel@tonic-gate * needs to know whether to continue, or stop processing the queue.
8387c478bd9Sstevel@tonic-gate */
8397c478bd9Sstevel@tonic-gate static int
rlmodrmsg(queue_t * q,mblk_t * mp)8407c478bd9Sstevel@tonic-gate rlmodrmsg(queue_t *q, mblk_t *mp)
8417c478bd9Sstevel@tonic-gate {
8427c478bd9Sstevel@tonic-gate unsigned char *tmp, *tmp1;
8437c478bd9Sstevel@tonic-gate mblk_t *newmp;
8447c478bd9Sstevel@tonic-gate size_t sz;
8457c478bd9Sstevel@tonic-gate ssize_t count, newcount = 0;
8467c478bd9Sstevel@tonic-gate struct rlmod_info *rmip = (struct rlmod_info *)q->q_ptr;
8477c478bd9Sstevel@tonic-gate
8487c478bd9Sstevel@tonic-gate /*
8497c478bd9Sstevel@tonic-gate * Eliminate any zero length messages here, so we don't filter EOFs
8507c478bd9Sstevel@tonic-gate * accidentally.
8517c478bd9Sstevel@tonic-gate */
8527c478bd9Sstevel@tonic-gate if (msgdsize(mp) == 0) {
8537c478bd9Sstevel@tonic-gate ASSERT(rmip->wndw_sz_hd_mp == NULL);
8547c478bd9Sstevel@tonic-gate goto out;
8557c478bd9Sstevel@tonic-gate }
8567c478bd9Sstevel@tonic-gate /*
8577c478bd9Sstevel@tonic-gate * Check if we have stored a previous message block because a window
8587c478bd9Sstevel@tonic-gate * update was split over TCP segments. If so, append the new one to
8597c478bd9Sstevel@tonic-gate * the stored one and process the stored one as if it just arrived.
8607c478bd9Sstevel@tonic-gate */
8617c478bd9Sstevel@tonic-gate if (rmip->wndw_sz_hd_mp != NULL) {
8627c478bd9Sstevel@tonic-gate linkb(rmip->wndw_sz_hd_mp, mp);
8637c478bd9Sstevel@tonic-gate mp = rmip->wndw_sz_hd_mp;
8647c478bd9Sstevel@tonic-gate rmip->wndw_sz_hd_mp = NULL;
8657c478bd9Sstevel@tonic-gate }
8667c478bd9Sstevel@tonic-gate newmp = mp;
8677c478bd9Sstevel@tonic-gate
8687c478bd9Sstevel@tonic-gate while (mp) {
8697c478bd9Sstevel@tonic-gate tmp = mp->b_rptr;
8707c478bd9Sstevel@tonic-gate /*
8717c478bd9Sstevel@tonic-gate * scan through the entire message block
8727c478bd9Sstevel@tonic-gate */
8737c478bd9Sstevel@tonic-gate while (tmp < mp->b_wptr) {
8747c478bd9Sstevel@tonic-gate /*
8757c478bd9Sstevel@tonic-gate * check for FF (rlogin magic escape sequence)
8767c478bd9Sstevel@tonic-gate */
8777c478bd9Sstevel@tonic-gate if (tmp[0] == RLOGIN_MAGIC) {
8787c478bd9Sstevel@tonic-gate /*
8797c478bd9Sstevel@tonic-gate * Update bytes read so far.
8807c478bd9Sstevel@tonic-gate */
8817c478bd9Sstevel@tonic-gate count = newcount + tmp - mp->b_rptr;
8827c478bd9Sstevel@tonic-gate /*
8837c478bd9Sstevel@tonic-gate * Pull together message chain in case
8847c478bd9Sstevel@tonic-gate * window escape is split across blocks.
8857c478bd9Sstevel@tonic-gate */
8867c478bd9Sstevel@tonic-gate if ((pullupmsg(newmp, -1)) == 0) {
8877c478bd9Sstevel@tonic-gate sz = msgdsize(newmp);
8887c478bd9Sstevel@tonic-gate recover(q, newmp, sz);
889*a8eee26aSToomas Soome return (0);
8907c478bd9Sstevel@tonic-gate }
8917c478bd9Sstevel@tonic-gate /*
8927c478bd9Sstevel@tonic-gate * pullupmsg results in newmp consuming
8937c478bd9Sstevel@tonic-gate * all message blocks in this chain, and
8947c478bd9Sstevel@tonic-gate * therefor mp wants updating.
8957c478bd9Sstevel@tonic-gate */
8967c478bd9Sstevel@tonic-gate mp = newmp;
8977c478bd9Sstevel@tonic-gate
8987c478bd9Sstevel@tonic-gate /*
8997c478bd9Sstevel@tonic-gate * adjust tmp to where we
9007c478bd9Sstevel@tonic-gate * stopped - count keeps track
9017c478bd9Sstevel@tonic-gate * of bytes read so far.
9027c478bd9Sstevel@tonic-gate * reset newcount = 0.
9037c478bd9Sstevel@tonic-gate */
9047c478bd9Sstevel@tonic-gate tmp = mp->b_rptr + count;
9057c478bd9Sstevel@tonic-gate newcount = 0;
9067c478bd9Sstevel@tonic-gate
9077c478bd9Sstevel@tonic-gate /*
9087c478bd9Sstevel@tonic-gate * Use the variable tmp1 to compute where
9097c478bd9Sstevel@tonic-gate * the end of the window escape (currently
9107c478bd9Sstevel@tonic-gate * the only rlogin protocol sequence), then
9117c478bd9Sstevel@tonic-gate * check to see if we got all those bytes.
9127c478bd9Sstevel@tonic-gate */
9137c478bd9Sstevel@tonic-gate tmp1 = tmp + 4 + sizeof (struct winsize);
9147c478bd9Sstevel@tonic-gate
9157c478bd9Sstevel@tonic-gate if (tmp1 > mp->b_wptr) {
9167c478bd9Sstevel@tonic-gate /*
9177c478bd9Sstevel@tonic-gate * All the window escape bytes aren't
9187c478bd9Sstevel@tonic-gate * in this TCP segment. Store this
9197c478bd9Sstevel@tonic-gate * mblk to one side so we can append
9207c478bd9Sstevel@tonic-gate * the rest of the escape to it when
9217c478bd9Sstevel@tonic-gate * its segment arrives.
9227c478bd9Sstevel@tonic-gate */
9237c478bd9Sstevel@tonic-gate rmip->wndw_sz_hd_mp = mp;
9247c478bd9Sstevel@tonic-gate return (TRUE);
9257c478bd9Sstevel@tonic-gate }
9267c478bd9Sstevel@tonic-gate /*
9277c478bd9Sstevel@tonic-gate * check for FF FF s s pattern
9287c478bd9Sstevel@tonic-gate */
9297c478bd9Sstevel@tonic-gate if ((tmp[1] == RLOGIN_MAGIC) &&
9307c478bd9Sstevel@tonic-gate (tmp[2] == 's') && (tmp[3] == 's')) {
9317c478bd9Sstevel@tonic-gate
9327c478bd9Sstevel@tonic-gate /*
9337c478bd9Sstevel@tonic-gate * If rlwinsetup returns an error,
9347c478bd9Sstevel@tonic-gate * we do recover with newmp which
9357c478bd9Sstevel@tonic-gate * points to new chain of mblks after
9367c478bd9Sstevel@tonic-gate * doing window control ioctls.
9377c478bd9Sstevel@tonic-gate * rlwinsetup returns newmp which
9387c478bd9Sstevel@tonic-gate * contains only data part.
9397c478bd9Sstevel@tonic-gate * Note that buried inside rlwinsetup
9407c478bd9Sstevel@tonic-gate * is where we do the putnext.
9417c478bd9Sstevel@tonic-gate */
9427c478bd9Sstevel@tonic-gate if (rlwinsetup(q, mp, tmp) == NULL) {
9437c478bd9Sstevel@tonic-gate sz = msgdsize(mp);
9447c478bd9Sstevel@tonic-gate recover(q, mp, sz);
945*a8eee26aSToomas Soome return (0);
9467c478bd9Sstevel@tonic-gate }
9477c478bd9Sstevel@tonic-gate /*
9487c478bd9Sstevel@tonic-gate * We have successfully consumed the
9497c478bd9Sstevel@tonic-gate * window sequence, but rlwinsetup()
9507c478bd9Sstevel@tonic-gate * and its children have moved memory
9517c478bd9Sstevel@tonic-gate * up underneath us. This means that
9527c478bd9Sstevel@tonic-gate * the byte underneath *tmp has not
9537c478bd9Sstevel@tonic-gate * been scanned now. We will now need
9547c478bd9Sstevel@tonic-gate * to rescan it.
9557c478bd9Sstevel@tonic-gate */
9567c478bd9Sstevel@tonic-gate continue;
9577c478bd9Sstevel@tonic-gate }
9587c478bd9Sstevel@tonic-gate }
9597c478bd9Sstevel@tonic-gate tmp++;
9607c478bd9Sstevel@tonic-gate }
9617c478bd9Sstevel@tonic-gate /*
9627c478bd9Sstevel@tonic-gate * bump newcount to include size of this particular block.
9637c478bd9Sstevel@tonic-gate */
9647c478bd9Sstevel@tonic-gate newcount += (mp->b_wptr - mp->b_rptr);
9657c478bd9Sstevel@tonic-gate mp = mp->b_cont;
9667c478bd9Sstevel@tonic-gate }
9677c478bd9Sstevel@tonic-gate /*
9687c478bd9Sstevel@tonic-gate * If we trimmed the message down to nothing to forward, don't
9697c478bd9Sstevel@tonic-gate * send any M_DATA message. (Don't want to send EOF!)
9707c478bd9Sstevel@tonic-gate */
9717c478bd9Sstevel@tonic-gate if (msgdsize(newmp) == 0) {
9727c478bd9Sstevel@tonic-gate freemsg(newmp);
9737c478bd9Sstevel@tonic-gate newmp = NULL;
9747c478bd9Sstevel@tonic-gate }
9757c478bd9Sstevel@tonic-gate out:
9767c478bd9Sstevel@tonic-gate if (newmp) {
9777c478bd9Sstevel@tonic-gate if (!canputnext(q)) {
9787c478bd9Sstevel@tonic-gate (void) putbq(q, newmp);
979*a8eee26aSToomas Soome return (0);
9807c478bd9Sstevel@tonic-gate } else {
9817c478bd9Sstevel@tonic-gate putnext(q, newmp);
9827c478bd9Sstevel@tonic-gate }
9837c478bd9Sstevel@tonic-gate }
9847c478bd9Sstevel@tonic-gate return (TRUE);
9857c478bd9Sstevel@tonic-gate }
9867c478bd9Sstevel@tonic-gate
9877c478bd9Sstevel@tonic-gate
9887c478bd9Sstevel@tonic-gate /*
9897c478bd9Sstevel@tonic-gate * This routine is called to handle window size changes.
9907c478bd9Sstevel@tonic-gate * The routine returns 1 on success and 0 on error (allocb failure).
9917c478bd9Sstevel@tonic-gate */
9927c478bd9Sstevel@tonic-gate static int
rlwinctl(queue_t * q,mblk_t * mp)9937c478bd9Sstevel@tonic-gate rlwinctl(queue_t *q, mblk_t *mp)
9947c478bd9Sstevel@tonic-gate {
9957c478bd9Sstevel@tonic-gate mblk_t *rl_msgp;
9967c478bd9Sstevel@tonic-gate struct iocblk *iocbp;
9977c478bd9Sstevel@tonic-gate struct rlmod_info *rmip = (struct rlmod_info *)q->q_ptr;
9987c478bd9Sstevel@tonic-gate
9997c478bd9Sstevel@tonic-gate TRACE_2(TR_FAC_RLOGINP, TR_RLOGINP_WINCTL_IN, "rlwinctl start: q %p, "
10007c478bd9Sstevel@tonic-gate "mp %p", q, mp);
10017c478bd9Sstevel@tonic-gate
100248bbca81SDaniel Hoffman rmip->oobdata[0] &= ~TIOCPKT_WINDOW; /* we know they heard */
10037c478bd9Sstevel@tonic-gate
10047c478bd9Sstevel@tonic-gate if ((rl_msgp = mkiocb(TIOCSWINSZ)) == NULL) {
10057c478bd9Sstevel@tonic-gate TRACE_2(TR_FAC_RLOGINP, TR_RLOGINP_WINCTL_OUT, "rlwinctl end: "
10067c478bd9Sstevel@tonic-gate "q %p, mp %p, allocb failed", q, mp);
10077c478bd9Sstevel@tonic-gate return (0);
10087c478bd9Sstevel@tonic-gate }
10097c478bd9Sstevel@tonic-gate
10107c478bd9Sstevel@tonic-gate /*
10117c478bd9Sstevel@tonic-gate * create an M_IOCTL message type.
10127c478bd9Sstevel@tonic-gate */
10137c478bd9Sstevel@tonic-gate rl_msgp->b_cont = mp;
10147c478bd9Sstevel@tonic-gate iocbp = (struct iocblk *)rl_msgp->b_rptr;
10157c478bd9Sstevel@tonic-gate iocbp->ioc_count = msgdsize(mp);
10167c478bd9Sstevel@tonic-gate
10177c478bd9Sstevel@tonic-gate putnext(q, rl_msgp);
10187c478bd9Sstevel@tonic-gate TRACE_2(TR_FAC_RLOGINP, TR_RLOGINP_WINCTL_OUT, "rlwinctl end: "
10197c478bd9Sstevel@tonic-gate "q %p, mp %p, done", q, mp);
10207c478bd9Sstevel@tonic-gate return (1);
10217c478bd9Sstevel@tonic-gate }
10227c478bd9Sstevel@tonic-gate
10237c478bd9Sstevel@tonic-gate /*
10247c478bd9Sstevel@tonic-gate * This routine sets up window size change protocol.
10257c478bd9Sstevel@tonic-gate * The routine returns the new mblk after issuing rlwinctl
10267c478bd9Sstevel@tonic-gate * for window size changes. New mblk contains only data part
10277c478bd9Sstevel@tonic-gate * of the message block. The routine returns 0 on error.
10287c478bd9Sstevel@tonic-gate */
10297c478bd9Sstevel@tonic-gate static mblk_t *
rlwinsetup(queue_t * q,mblk_t * mp,unsigned char * blk)10307c478bd9Sstevel@tonic-gate rlwinsetup(queue_t *q, mblk_t *mp, unsigned char *blk)
10317c478bd9Sstevel@tonic-gate {
10327c478bd9Sstevel@tonic-gate mblk_t *mp1;
10337c478bd9Sstevel@tonic-gate unsigned char *jmpmp;
10347c478bd9Sstevel@tonic-gate ssize_t left = 0;
10357c478bd9Sstevel@tonic-gate struct winsize win;
10367c478bd9Sstevel@tonic-gate
10377c478bd9Sstevel@tonic-gate /*
10387c478bd9Sstevel@tonic-gate * Set jmpmp to where to jump, to get just past the end of the
10397c478bd9Sstevel@tonic-gate * window size protocol sequence.
10407c478bd9Sstevel@tonic-gate */
10417c478bd9Sstevel@tonic-gate jmpmp = (blk + 4 + sizeof (struct winsize));
10427c478bd9Sstevel@tonic-gate left = mp->b_wptr - jmpmp;
10437c478bd9Sstevel@tonic-gate
10447c478bd9Sstevel@tonic-gate if ((mp1 = allocb(sizeof (struct winsize), BPRI_MED)) == NULL)
10457c478bd9Sstevel@tonic-gate return (0);
10467c478bd9Sstevel@tonic-gate mp1->b_datap->db_type = M_DATA;
10477c478bd9Sstevel@tonic-gate mp1->b_wptr = mp1->b_rptr + sizeof (struct winsize);
10487c478bd9Sstevel@tonic-gate bcopy(blk + 4, &win, sizeof (struct winsize));
10497c478bd9Sstevel@tonic-gate win.ws_row = ntohs(win.ws_row);
10507c478bd9Sstevel@tonic-gate win.ws_col = ntohs(win.ws_col);
10517c478bd9Sstevel@tonic-gate win.ws_xpixel = ntohs(win.ws_xpixel);
10527c478bd9Sstevel@tonic-gate win.ws_ypixel = ntohs(win.ws_ypixel);
10537c478bd9Sstevel@tonic-gate bcopy(&win, mp1->b_rptr, sizeof (struct winsize));
10547c478bd9Sstevel@tonic-gate
1055*a8eee26aSToomas Soome if ((rlwinctl(q, mp1)) == 0) {
10567c478bd9Sstevel@tonic-gate freeb(mp1);
10577c478bd9Sstevel@tonic-gate return (0);
10587c478bd9Sstevel@tonic-gate }
10597c478bd9Sstevel@tonic-gate if (left > 0) {
10607c478bd9Sstevel@tonic-gate /*
10617c478bd9Sstevel@tonic-gate * Must delete the window size protocol sequence. We do
10627c478bd9Sstevel@tonic-gate * this by sliding all the stuff after the sequence (jmpmp)
10637c478bd9Sstevel@tonic-gate * to where the sequence itself began (blk).
10647c478bd9Sstevel@tonic-gate */
10657c478bd9Sstevel@tonic-gate bcopy(jmpmp, blk, left);
10667c478bd9Sstevel@tonic-gate mp->b_wptr = blk + left;
10677c478bd9Sstevel@tonic-gate } else
10687c478bd9Sstevel@tonic-gate mp->b_wptr = blk;
10697c478bd9Sstevel@tonic-gate return (mp);
10707c478bd9Sstevel@tonic-gate }
10717c478bd9Sstevel@tonic-gate
10727c478bd9Sstevel@tonic-gate /*
10737c478bd9Sstevel@tonic-gate * When an ioctl changes software flow control on the tty, we must notify
10747c478bd9Sstevel@tonic-gate * the rlogin client, so it can adjust its behavior appropriately. This
10757c478bd9Sstevel@tonic-gate * routine, called from either the put or service routine, determines if
10767c478bd9Sstevel@tonic-gate * the flow handling has changed. If so, it tries to send the indication
10777c478bd9Sstevel@tonic-gate * to the client. It returns true or false depending upon whether the
10787c478bd9Sstevel@tonic-gate * message was fully processed. If it wasn't fully processed it queues
10797c478bd9Sstevel@tonic-gate * the message for retry later when resources
10807c478bd9Sstevel@tonic-gate * (allocb/canputnext) are available.
10817c478bd9Sstevel@tonic-gate */
10827c478bd9Sstevel@tonic-gate static boolean_t
tty_flow(queue_t * q,struct rlmod_info * rmip,mblk_t * mp)10837c478bd9Sstevel@tonic-gate tty_flow(queue_t *q, struct rlmod_info *rmip, mblk_t *mp)
10847c478bd9Sstevel@tonic-gate {
10857c478bd9Sstevel@tonic-gate struct iocblk *ioc;
10867c478bd9Sstevel@tonic-gate struct termios *tp;
10877c478bd9Sstevel@tonic-gate struct termio *ti;
10887c478bd9Sstevel@tonic-gate int stop, ixon;
10897c478bd9Sstevel@tonic-gate mblk_t *tmpmp;
10907c478bd9Sstevel@tonic-gate char cntl;
10917c478bd9Sstevel@tonic-gate int error;
10927c478bd9Sstevel@tonic-gate
10937c478bd9Sstevel@tonic-gate ioc = (struct iocblk *)mp->b_rptr;
10947c478bd9Sstevel@tonic-gate switch (ioc->ioc_cmd) {
10957c478bd9Sstevel@tonic-gate
10967c478bd9Sstevel@tonic-gate /*
10977c478bd9Sstevel@tonic-gate * If it is a tty ioctl, save the output flow
10987c478bd9Sstevel@tonic-gate * control flag and the start and stop flow control
10997c478bd9Sstevel@tonic-gate * characters if they are available.
11007c478bd9Sstevel@tonic-gate */
11017c478bd9Sstevel@tonic-gate case TCSETS:
11027c478bd9Sstevel@tonic-gate case TCSETSW:
11037c478bd9Sstevel@tonic-gate case TCSETSF:
11047c478bd9Sstevel@tonic-gate error = miocpullup(mp, sizeof (struct termios));
11057c478bd9Sstevel@tonic-gate if (error != 0) {
11067c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, error);
11077c478bd9Sstevel@tonic-gate return (B_TRUE);
11087c478bd9Sstevel@tonic-gate }
11097c478bd9Sstevel@tonic-gate tp = (struct termios *)(mp->b_cont->b_rptr);
11107c478bd9Sstevel@tonic-gate rmip->stopc = tp->c_cc[VSTOP];
11117c478bd9Sstevel@tonic-gate rmip->startc = tp->c_cc[VSTART];
11127c478bd9Sstevel@tonic-gate ixon = tp->c_iflag & IXON;
11137c478bd9Sstevel@tonic-gate break;
11147c478bd9Sstevel@tonic-gate
11157c478bd9Sstevel@tonic-gate case TCSETA:
11167c478bd9Sstevel@tonic-gate case TCSETAW:
11177c478bd9Sstevel@tonic-gate case TCSETAF:
11187c478bd9Sstevel@tonic-gate error = miocpullup(mp, sizeof (struct termio));
11197c478bd9Sstevel@tonic-gate if (error != 0) {
11207c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, error);
11217c478bd9Sstevel@tonic-gate return (B_TRUE);
11227c478bd9Sstevel@tonic-gate }
11237c478bd9Sstevel@tonic-gate ti = (struct termio *)(mp->b_cont->b_rptr);
11247c478bd9Sstevel@tonic-gate ixon = ti->c_iflag & IXON;
11257c478bd9Sstevel@tonic-gate break;
11267c478bd9Sstevel@tonic-gate
11277c478bd9Sstevel@tonic-gate default:
11287c478bd9Sstevel@tonic-gate /*
11297c478bd9Sstevel@tonic-gate * This function must never be called for an M_IOCTL
11307c478bd9Sstevel@tonic-gate * except the listed ones.
11317c478bd9Sstevel@tonic-gate */
11327c478bd9Sstevel@tonic-gate #ifdef DEBUG
11337c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC,
11347c478bd9Sstevel@tonic-gate "rloginmod: tty_flow: bad ioctl 0x%x", ioc->ioc_cmd);
11357c478bd9Sstevel@tonic-gate #else
11367c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EINVAL);
11377c478bd9Sstevel@tonic-gate return (B_TRUE);
11387c478bd9Sstevel@tonic-gate #endif
11397c478bd9Sstevel@tonic-gate }
11407c478bd9Sstevel@tonic-gate /*
11417c478bd9Sstevel@tonic-gate * If tty ioctl processing is done, check for stopmode
11427c478bd9Sstevel@tonic-gate */
11437c478bd9Sstevel@tonic-gate stop = (ixon && (rmip->stopc == CTRL('s')) &&
1144*a8eee26aSToomas Soome (rmip->startc == CTRL('q')));
11457c478bd9Sstevel@tonic-gate if (rmip->stopmode == TIOCPKT_NOSTOP) {
11467c478bd9Sstevel@tonic-gate if (stop) {
11477c478bd9Sstevel@tonic-gate cntl = rmip->oobdata[0] | TIOCPKT_DOSTOP;
11487c478bd9Sstevel@tonic-gate if ((tmpmp = make_expmblk(cntl)) == NULL) {
11497c478bd9Sstevel@tonic-gate recover(q, mp, sizeof (mblk_t));
11507c478bd9Sstevel@tonic-gate return (B_FALSE);
11517c478bd9Sstevel@tonic-gate }
11527c478bd9Sstevel@tonic-gate if (!canputnext(q)) {
11537c478bd9Sstevel@tonic-gate freemsg(tmpmp);
11547c478bd9Sstevel@tonic-gate return (B_FALSE);
11557c478bd9Sstevel@tonic-gate }
11567c478bd9Sstevel@tonic-gate putnext(q, tmpmp);
11577c478bd9Sstevel@tonic-gate rmip->stopmode = TIOCPKT_DOSTOP;
11587c478bd9Sstevel@tonic-gate }
11597c478bd9Sstevel@tonic-gate } else {
11607c478bd9Sstevel@tonic-gate if (!stop) {
11617c478bd9Sstevel@tonic-gate cntl = rmip->oobdata[0] | TIOCPKT_NOSTOP;
11627c478bd9Sstevel@tonic-gate if ((tmpmp = make_expmblk(cntl)) == NULL) {
11637c478bd9Sstevel@tonic-gate recover(q, mp, sizeof (mblk_t));
11647c478bd9Sstevel@tonic-gate return (B_FALSE);
11657c478bd9Sstevel@tonic-gate }
11667c478bd9Sstevel@tonic-gate if (!canputnext(q)) {
11677c478bd9Sstevel@tonic-gate freemsg(tmpmp);
11687c478bd9Sstevel@tonic-gate return (B_FALSE);
11697c478bd9Sstevel@tonic-gate }
11707c478bd9Sstevel@tonic-gate putnext(q, tmpmp);
11717c478bd9Sstevel@tonic-gate rmip->stopmode = TIOCPKT_NOSTOP;
11727c478bd9Sstevel@tonic-gate }
11737c478bd9Sstevel@tonic-gate }
11747c478bd9Sstevel@tonic-gate
11757c478bd9Sstevel@tonic-gate miocack(q, mp, 0, 0);
11767c478bd9Sstevel@tonic-gate return (B_TRUE);
11777c478bd9Sstevel@tonic-gate }
11787c478bd9Sstevel@tonic-gate
11797c478bd9Sstevel@tonic-gate /* rlmodwioctl - handle M_IOCTL messages on the write queue. */
11807c478bd9Sstevel@tonic-gate
11817c478bd9Sstevel@tonic-gate static boolean_t
rlmodwioctl(queue_t * q,mblk_t * mp)11827c478bd9Sstevel@tonic-gate rlmodwioctl(queue_t *q, mblk_t *mp)
11837c478bd9Sstevel@tonic-gate {
11847c478bd9Sstevel@tonic-gate struct iocblk *ioc;
11857c478bd9Sstevel@tonic-gate struct rlmod_info *rmip = (struct rlmod_info *)q->q_ptr;
11867c478bd9Sstevel@tonic-gate int error;
11877c478bd9Sstevel@tonic-gate
11887c478bd9Sstevel@tonic-gate ioc = (struct iocblk *)mp->b_rptr;
11897c478bd9Sstevel@tonic-gate switch (ioc->ioc_cmd) {
11907c478bd9Sstevel@tonic-gate
11917c478bd9Sstevel@tonic-gate /*
11927c478bd9Sstevel@tonic-gate * This is a special ioctl to reenable the queue.
11937c478bd9Sstevel@tonic-gate * The initial data read from the stream head is
11947c478bd9Sstevel@tonic-gate * put back on the queue.
11957c478bd9Sstevel@tonic-gate */
11967c478bd9Sstevel@tonic-gate case RL_IOC_ENABLE:
11977c478bd9Sstevel@tonic-gate /*
11987c478bd9Sstevel@tonic-gate * Send negative ack if RL_DISABLED flag is not set
11997c478bd9Sstevel@tonic-gate */
12007c478bd9Sstevel@tonic-gate
12017c478bd9Sstevel@tonic-gate if (!(rmip->flags & RL_DISABLED)) {
12027c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EINVAL);
12037c478bd9Sstevel@tonic-gate break;
12047c478bd9Sstevel@tonic-gate }
12057c478bd9Sstevel@tonic-gate if (mp->b_cont) {
12067c478bd9Sstevel@tonic-gate (void) putbq(RD(q), mp->b_cont);
12077c478bd9Sstevel@tonic-gate mp->b_cont = NULL;
12087c478bd9Sstevel@tonic-gate }
12097c478bd9Sstevel@tonic-gate
12107c478bd9Sstevel@tonic-gate if (rmip->flags & RL_DISABLED)
12117c478bd9Sstevel@tonic-gate rmip->flags &= ~RL_DISABLED;
12127c478bd9Sstevel@tonic-gate qenable(RD(q));
12137c478bd9Sstevel@tonic-gate miocack(q, mp, 0, 0);
12147c478bd9Sstevel@tonic-gate TRACE_3(TR_FAC_RLOGINP, TR_RLOGINP_WPUT_OUT,
12157c478bd9Sstevel@tonic-gate "rlmodwput end: q %p, mp %p, %s",
12167c478bd9Sstevel@tonic-gate q, mp, "IOCACK enable");
12177c478bd9Sstevel@tonic-gate return (B_TRUE);
12187c478bd9Sstevel@tonic-gate
12197c478bd9Sstevel@tonic-gate /*
12207c478bd9Sstevel@tonic-gate * If it is a tty ioctl, save the output flow
12217c478bd9Sstevel@tonic-gate * control flag and the start and stop flow control
12227c478bd9Sstevel@tonic-gate * characters if they are available.
12237c478bd9Sstevel@tonic-gate */
12247c478bd9Sstevel@tonic-gate case TCSETS:
12257c478bd9Sstevel@tonic-gate case TCSETSW:
12267c478bd9Sstevel@tonic-gate case TCSETSF:
12277c478bd9Sstevel@tonic-gate case TCSETA:
12287c478bd9Sstevel@tonic-gate case TCSETAW:
12297c478bd9Sstevel@tonic-gate case TCSETAF:
12307c478bd9Sstevel@tonic-gate return (tty_flow(q, rmip, mp));
12317c478bd9Sstevel@tonic-gate
12327c478bd9Sstevel@tonic-gate #ifdef DEBUG
12337c478bd9Sstevel@tonic-gate case TIOCSWINSZ:
12347c478bd9Sstevel@tonic-gate case TIOCSTI:
12357c478bd9Sstevel@tonic-gate case TCSBRK:
12367c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EINVAL);
12377c478bd9Sstevel@tonic-gate break;
12387c478bd9Sstevel@tonic-gate #endif
12397c478bd9Sstevel@tonic-gate case CRYPTPASSTHRU:
12407c478bd9Sstevel@tonic-gate error = miocpullup(mp, sizeof (uchar_t));
12417c478bd9Sstevel@tonic-gate if (error != 0) {
12427c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, error);
12437c478bd9Sstevel@tonic-gate break;
12447c478bd9Sstevel@tonic-gate }
12457c478bd9Sstevel@tonic-gate if (*(mp->b_cont->b_rptr) == 0x01)
12467c478bd9Sstevel@tonic-gate rmip->flags |= RL_IOCPASSTHRU;
12477c478bd9Sstevel@tonic-gate else
12487c478bd9Sstevel@tonic-gate rmip->flags &= ~RL_IOCPASSTHRU;
12497c478bd9Sstevel@tonic-gate
1250*a8eee26aSToomas Soome miocack(q, mp, 0, 0);
12517c478bd9Sstevel@tonic-gate break;
12527c478bd9Sstevel@tonic-gate
12537c478bd9Sstevel@tonic-gate default:
12547c478bd9Sstevel@tonic-gate if (rmip->flags & RL_IOCPASSTHRU) {
12557c478bd9Sstevel@tonic-gate putnext(q, mp);
12567c478bd9Sstevel@tonic-gate } else {
12577c478bd9Sstevel@tonic-gate #ifdef DEBUG
12587c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE,
1259*a8eee26aSToomas Soome "rlmodwioctl: unexpected ioctl type 0x%x",
1260*a8eee26aSToomas Soome ioc->ioc_cmd);
12617c478bd9Sstevel@tonic-gate #endif
12627c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, EINVAL);
12637c478bd9Sstevel@tonic-gate }
12647c478bd9Sstevel@tonic-gate }
12657c478bd9Sstevel@tonic-gate return (B_TRUE);
12667c478bd9Sstevel@tonic-gate }
12677c478bd9Sstevel@tonic-gate
12687c478bd9Sstevel@tonic-gate static void
rlmod_timer(void * arg)12697c478bd9Sstevel@tonic-gate rlmod_timer(void *arg)
12707c478bd9Sstevel@tonic-gate {
12717c478bd9Sstevel@tonic-gate queue_t *q = arg;
12727c478bd9Sstevel@tonic-gate struct rlmod_info *rmip = (struct rlmod_info *)q->q_ptr;
12737c478bd9Sstevel@tonic-gate
12747c478bd9Sstevel@tonic-gate ASSERT(rmip);
12757c478bd9Sstevel@tonic-gate if (q->q_flag & QREADR) {
12767c478bd9Sstevel@tonic-gate ASSERT(rmip->rtimoutid);
12777c478bd9Sstevel@tonic-gate rmip->rtimoutid = 0;
12787c478bd9Sstevel@tonic-gate } else {
12797c478bd9Sstevel@tonic-gate ASSERT(rmip->wtimoutid);
12807c478bd9Sstevel@tonic-gate rmip->wtimoutid = 0;
12817c478bd9Sstevel@tonic-gate }
12827c478bd9Sstevel@tonic-gate enableok(q);
12837c478bd9Sstevel@tonic-gate qenable(q);
12847c478bd9Sstevel@tonic-gate }
12857c478bd9Sstevel@tonic-gate
12867c478bd9Sstevel@tonic-gate static void
rlmod_buffer(void * arg)12877c478bd9Sstevel@tonic-gate rlmod_buffer(void *arg)
12887c478bd9Sstevel@tonic-gate {
12897c478bd9Sstevel@tonic-gate queue_t *q = arg;
12907c478bd9Sstevel@tonic-gate struct rlmod_info *rmip = (struct rlmod_info *)q->q_ptr;
12917c478bd9Sstevel@tonic-gate
12927c478bd9Sstevel@tonic-gate ASSERT(rmip);
12937c478bd9Sstevel@tonic-gate if (q->q_flag & QREADR) {
12947c478bd9Sstevel@tonic-gate ASSERT(rmip->rbufcid);
12957c478bd9Sstevel@tonic-gate rmip->rbufcid = 0;
12967c478bd9Sstevel@tonic-gate } else {
12977c478bd9Sstevel@tonic-gate ASSERT(rmip->wbufcid);
12987c478bd9Sstevel@tonic-gate rmip->wbufcid = 0;
12997c478bd9Sstevel@tonic-gate }
13007c478bd9Sstevel@tonic-gate enableok(q);
13017c478bd9Sstevel@tonic-gate qenable(q);
13027c478bd9Sstevel@tonic-gate }
13037c478bd9Sstevel@tonic-gate
13047c478bd9Sstevel@tonic-gate static void
recover(queue_t * q,mblk_t * mp,size_t size)13057c478bd9Sstevel@tonic-gate recover(queue_t *q, mblk_t *mp, size_t size)
13067c478bd9Sstevel@tonic-gate {
13077c478bd9Sstevel@tonic-gate /*
13087c478bd9Sstevel@tonic-gate * Avoid re-enabling the queue.
13097c478bd9Sstevel@tonic-gate */
13107c478bd9Sstevel@tonic-gate ASSERT(mp->b_datap->db_type < QPCTL);
13117c478bd9Sstevel@tonic-gate
13127c478bd9Sstevel@tonic-gate noenable(q);
13137c478bd9Sstevel@tonic-gate (void) putbq(q, mp);
13147c478bd9Sstevel@tonic-gate recover1(q, size);
13157c478bd9Sstevel@tonic-gate }
13167c478bd9Sstevel@tonic-gate
13177c478bd9Sstevel@tonic-gate static void
recover1(queue_t * q,size_t size)13187c478bd9Sstevel@tonic-gate recover1(queue_t *q, size_t size)
13197c478bd9Sstevel@tonic-gate {
13207c478bd9Sstevel@tonic-gate struct rlmod_info *rmip = (struct rlmod_info *)q->q_ptr;
13217c478bd9Sstevel@tonic-gate timeout_id_t tid;
13227c478bd9Sstevel@tonic-gate bufcall_id_t bid;
13237c478bd9Sstevel@tonic-gate
13247c478bd9Sstevel@tonic-gate /*
13257c478bd9Sstevel@tonic-gate * Make sure there is at most one outstanding request per queue.
13267c478bd9Sstevel@tonic-gate */
13277c478bd9Sstevel@tonic-gate if (q->q_flag & QREADR) {
13287c478bd9Sstevel@tonic-gate if (rmip->rtimoutid || rmip->rbufcid)
13297c478bd9Sstevel@tonic-gate return;
13307c478bd9Sstevel@tonic-gate } else {
13317c478bd9Sstevel@tonic-gate if (rmip->wtimoutid || rmip->wbufcid)
13327c478bd9Sstevel@tonic-gate return;
13337c478bd9Sstevel@tonic-gate }
13347c478bd9Sstevel@tonic-gate if (!(bid = qbufcall(RD(q), size, BPRI_MED, rlmod_buffer, q))) {
13357c478bd9Sstevel@tonic-gate tid = qtimeout(RD(q), rlmod_timer, q, SIMWAIT);
13367c478bd9Sstevel@tonic-gate if (q->q_flag & QREADR)
13377c478bd9Sstevel@tonic-gate rmip->rtimoutid = tid;
13387c478bd9Sstevel@tonic-gate else
13397c478bd9Sstevel@tonic-gate rmip->wtimoutid = tid;
13407c478bd9Sstevel@tonic-gate } else {
13417c478bd9Sstevel@tonic-gate if (q->q_flag & QREADR)
13427c478bd9Sstevel@tonic-gate rmip->rbufcid = bid;
13437c478bd9Sstevel@tonic-gate else
13447c478bd9Sstevel@tonic-gate rmip->wbufcid = bid;
13457c478bd9Sstevel@tonic-gate }
13467c478bd9Sstevel@tonic-gate }
1347