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