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