1 /* $NetBSD: state.c,v 1.31 2019/02/03 03:19:25 mrg Exp $ */ 2 3 /* 4 * Copyright (c) 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #ifndef lint 34 #if 0 35 static char sccsid[] = "@(#)state.c 8.5 (Berkeley) 5/30/95"; 36 #else 37 __RCSID("$NetBSD: state.c,v 1.31 2019/02/03 03:19:25 mrg Exp $"); 38 #endif 39 #endif /* not lint */ 40 41 #include <ctype.h> 42 #include <stdarg.h> 43 44 #include "telnetd.h" 45 46 static int envvarok(char *); 47 48 int not42 = 1; 49 50 /* 51 * Buffer for sub-options, and macros 52 * for suboptions buffer manipulations 53 */ 54 unsigned char subbuffer[4096], *subpointer= subbuffer, *subend= subbuffer; 55 56 #define SB_CLEAR() subpointer = subbuffer 57 #define SB_TERM() { subend = subpointer; SB_CLEAR(); } 58 #define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \ 59 *subpointer++ = (c); \ 60 } 61 #define SB_GET() ((*subpointer++)&0xff) 62 #define SB_EOF() (subpointer >= subend) 63 #define SB_LEN() (subend - subpointer) 64 65 #ifdef ENV_HACK 66 unsigned char *subsave; 67 #define SB_SAVE() subsave = subpointer; 68 #define SB_RESTORE() subpointer = subsave; 69 #endif 70 71 72 /* 73 * State for recv fsm 74 */ 75 #define TS_DATA 0 /* base state */ 76 #define TS_IAC 1 /* look for double IAC's */ 77 #define TS_CR 2 /* CR-LF ->'s CR */ 78 #define TS_SB 3 /* throw away begin's... */ 79 #define TS_SE 4 /* ...end's (suboption negotiation) */ 80 #define TS_WILL 5 /* will option negotiation */ 81 #define TS_WONT 6 /* wont " */ 82 #define TS_DO 7 /* do " */ 83 #define TS_DONT 8 /* dont " */ 84 85 void 86 telrcv(void) 87 { 88 int c; 89 static int state = TS_DATA; 90 91 while (ncc > 0) { 92 if ((&ptyobuf[BUFSIZ] - pfrontp) < 2) 93 break; 94 c = *netip++ & 0377, ncc--; 95 #ifdef ENCRYPTION 96 if (decrypt_input) 97 c = (*decrypt_input)(c); 98 #endif /* ENCRYPTION */ 99 switch (state) { 100 101 case TS_CR: 102 state = TS_DATA; 103 /* Strip off \n or \0 after a \r */ 104 if ((c == 0) || (c == '\n')) { 105 break; 106 } 107 /* FALL THROUGH */ 108 109 case TS_DATA: 110 if (c == IAC) { 111 state = TS_IAC; 112 break; 113 } 114 /* 115 * We now map \r\n ==> \r for pragmatic reasons. 116 * Many client implementations send \r\n when 117 * the user hits the CarriageReturn key. 118 * 119 * We USED to map \r\n ==> \n, since \r\n says 120 * that we want to be in column 1 of the next 121 * printable line, and \n is the standard 122 * unix way of saying that (\r is only good 123 * if CRMOD is set, which it normally is). 124 */ 125 if ((c == '\r') && his_state_is_wont(TELOPT_BINARY)) { 126 int nc = *netip; 127 #ifdef ENCRYPTION 128 if (decrypt_input) 129 nc = (*decrypt_input)(nc & 0xff); 130 #endif /* ENCRYPTION */ 131 #ifdef LINEMODE 132 /* 133 * If we are operating in linemode, 134 * convert to local end-of-line. 135 */ 136 if (linemode && (ncc > 0) && (('\n' == nc) || 137 ((0 == nc) && tty_iscrnl())) ) { 138 netip++; ncc--; 139 c = '\n'; 140 } else 141 #endif 142 { 143 #ifdef ENCRYPTION 144 if (decrypt_input) 145 (void)(*decrypt_input)(-1); 146 #endif /* ENCRYPTION */ 147 state = TS_CR; 148 } 149 } 150 *pfrontp++ = c; 151 break; 152 153 case TS_IAC: 154 gotiac: switch (c) { 155 156 /* 157 * Send the process on the pty side an 158 * interrupt. Do this with a NULL or 159 * interrupt char; depending on the tty mode. 160 */ 161 case IP: 162 DIAG(TD_OPTIONS, 163 printoption("td: recv IAC", c)); 164 interrupt(); 165 break; 166 167 case BREAK: 168 DIAG(TD_OPTIONS, 169 printoption("td: recv IAC", c)); 170 sendbrk(); 171 break; 172 173 /* 174 * Are You There? 175 */ 176 case AYT: 177 DIAG(TD_OPTIONS, 178 printoption("td: recv IAC", c)); 179 recv_ayt(); 180 break; 181 182 /* 183 * Abort Output 184 */ 185 case AO: 186 { 187 DIAG(TD_OPTIONS, 188 printoption("td: recv IAC", c)); 189 ptyflush(); /* half-hearted */ 190 init_termbuf(); 191 192 if (slctab[SLC_AO].sptr && 193 *slctab[SLC_AO].sptr != (cc_t)(_POSIX_VDISABLE)) { 194 *pfrontp++ = 195 (unsigned char)*slctab[SLC_AO].sptr; 196 } 197 198 netclear(); /* clear buffer back */ 199 output_data("%c%c", IAC, DM); 200 neturg = nfrontp - 1; /* off by one XXX */ 201 DIAG(TD_OPTIONS, 202 printoption("td: send IAC", DM)); 203 break; 204 } 205 206 /* 207 * Erase Character and 208 * Erase Line 209 */ 210 case EC: 211 case EL: 212 { 213 cc_t ch; 214 215 DIAG(TD_OPTIONS, 216 printoption("td: recv IAC", c)); 217 ptyflush(); /* half-hearted */ 218 init_termbuf(); 219 if (c == EC) 220 ch = *slctab[SLC_EC].sptr; 221 else 222 ch = *slctab[SLC_EL].sptr; 223 if (ch != (cc_t)(_POSIX_VDISABLE)) 224 *pfrontp++ = (unsigned char)ch; 225 break; 226 } 227 228 /* 229 * Check for urgent data... 230 */ 231 case DM: 232 DIAG(TD_OPTIONS, 233 printoption("td: recv IAC", c)); 234 SYNCHing = stilloob(net); 235 settimer(gotDM); 236 break; 237 238 239 /* 240 * Begin option subnegotiation... 241 */ 242 case SB: 243 state = TS_SB; 244 SB_CLEAR(); 245 continue; 246 247 case WILL: 248 state = TS_WILL; 249 continue; 250 251 case WONT: 252 state = TS_WONT; 253 continue; 254 255 case DO: 256 state = TS_DO; 257 continue; 258 259 case DONT: 260 state = TS_DONT; 261 continue; 262 case EOR: 263 if (his_state_is_will(TELOPT_EOR)) 264 doeof(); 265 break; 266 267 /* 268 * Handle RFC 10xx Telnet linemode option additions 269 * to command stream (EOF, SUSP, ABORT). 270 */ 271 case xEOF: 272 doeof(); 273 break; 274 275 case SUSP: 276 sendsusp(); 277 break; 278 279 case ABORT: 280 sendbrk(); 281 break; 282 283 case IAC: 284 *pfrontp++ = c; 285 break; 286 } 287 state = TS_DATA; 288 break; 289 290 case TS_SB: 291 if (c == IAC) { 292 state = TS_SE; 293 } else { 294 SB_ACCUM(c); 295 } 296 break; 297 298 case TS_SE: 299 if (c != SE) { 300 if (c != IAC) { 301 /* 302 * bad form of suboption negotiation. 303 * handle it in such a way as to avoid 304 * damage to local state. Parse 305 * suboption buffer found so far, 306 * then treat remaining stream as 307 * another command sequence. 308 */ 309 310 /* for DIAGNOSTICS */ 311 SB_ACCUM(IAC); 312 SB_ACCUM(c); 313 subpointer -= 2; 314 315 SB_TERM(); 316 suboption(); 317 state = TS_IAC; 318 goto gotiac; 319 } 320 SB_ACCUM(c); 321 state = TS_SB; 322 } else { 323 /* for DIAGNOSTICS */ 324 SB_ACCUM(IAC); 325 SB_ACCUM(SE); 326 subpointer -= 2; 327 328 SB_TERM(); 329 suboption(); /* handle sub-option */ 330 state = TS_DATA; 331 } 332 break; 333 334 case TS_WILL: 335 willoption(c); 336 state = TS_DATA; 337 continue; 338 339 case TS_WONT: 340 wontoption(c); 341 state = TS_DATA; 342 continue; 343 344 case TS_DO: 345 dooption(c); 346 state = TS_DATA; 347 continue; 348 349 case TS_DONT: 350 dontoption(c); 351 state = TS_DATA; 352 continue; 353 354 default: 355 syslog(LOG_ERR, "panic state=%d", state); 356 printf("telnetd: panic state=%d\n", state); 357 exit(1); 358 } 359 } 360 } /* end of telrcv */ 361 362 /* 363 * The will/wont/do/dont state machines are based on Dave Borman's 364 * Telnet option processing state machine. 365 * 366 * These correspond to the following states: 367 * my_state = the last negotiated state 368 * want_state = what I want the state to go to 369 * want_resp = how many requests I have sent 370 * All state defaults are negative, and resp defaults to 0. 371 * 372 * When initiating a request to change state to new_state: 373 * 374 * if ((want_resp == 0 && new_state == my_state) || want_state == new_state) { 375 * do nothing; 376 * } else { 377 * want_state = new_state; 378 * send new_state; 379 * want_resp++; 380 * } 381 * 382 * When receiving new_state: 383 * 384 * if (want_resp) { 385 * want_resp--; 386 * if (want_resp && (new_state == my_state)) 387 * want_resp--; 388 * } 389 * if ((want_resp == 0) && (new_state != want_state)) { 390 * if (ok_to_switch_to new_state) 391 * want_state = new_state; 392 * else 393 * want_resp++; 394 * send want_state; 395 * } 396 * my_state = new_state; 397 * 398 * Note that new_state is implied in these functions by the function itself. 399 * will and do imply positive new_state, wont and dont imply negative. 400 * 401 * Finally, there is one catch. If we send a negative response to a 402 * positive request, my_state will be the positive while want_state will 403 * remain negative. my_state will revert to negative when the negative 404 * acknowledgment arrives from the peer. Thus, my_state generally tells 405 * us not only the last negotiated state, but also tells us what the peer 406 * wants to be doing as well. It is important to understand this difference 407 * as we may wish to be processing data streams based on our desired state 408 * (want_state) or based on what the peer thinks the state is (my_state). 409 * 410 * This all works fine because if the peer sends a positive request, the data 411 * that we receive prior to negative acknowledgment will probably be affected 412 * by the positive state, and we can process it as such (if we can; if we 413 * can't then it really doesn't matter). If it is that important, then the 414 * peer probably should be buffering until this option state negotiation 415 * is complete. 416 * 417 */ 418 void 419 send_do(int option, int init) 420 { 421 if (init) { 422 if ((do_dont_resp[option] == 0 && his_state_is_will(option)) || 423 his_want_state_is_will(option)) 424 return; 425 /* 426 * Special case for TELOPT_TM: We send a DO, but pretend 427 * that we sent a DONT, so that we can send more DOs if 428 * we want to. 429 */ 430 if (option == TELOPT_TM) 431 set_his_want_state_wont(option); 432 else 433 set_his_want_state_will(option); 434 do_dont_resp[option]++; 435 } 436 (void) output_data("%c%c%c", IAC, DO, option); 437 438 DIAG(TD_OPTIONS, printoption("td: send do", option)); 439 } 440 441 #ifdef LINEMODE 442 extern void doclientstat(void); 443 #endif 444 #if 0 445 #ifdef AUTHENTICATION 446 extern void auth_request(void); /* libtelnet */ 447 #endif 448 #ifdef ENCRYPTION 449 extern void encrypt_send_support(void); 450 #endif /* ENCRYPTION */ 451 #endif 452 453 void 454 willoption(int option) 455 { 456 int changeok = 0; 457 void (*func)(void) = 0; 458 459 /* 460 * process input from peer. 461 */ 462 463 DIAG(TD_OPTIONS, printoption("td: recv will", option)); 464 465 if (do_dont_resp[option]) { 466 do_dont_resp[option]--; 467 if (do_dont_resp[option] && his_state_is_will(option)) 468 do_dont_resp[option]--; 469 } 470 if (do_dont_resp[option] == 0) { 471 if (his_want_state_is_wont(option)) { 472 switch (option) { 473 474 case TELOPT_BINARY: 475 init_termbuf(); 476 tty_binaryin(1); 477 set_termbuf(); 478 changeok++; 479 break; 480 481 case TELOPT_ECHO: 482 /* 483 * See comments below for more info. 484 */ 485 not42 = 0; /* looks like a 4.2 system */ 486 break; 487 488 case TELOPT_TM: 489 #if defined(LINEMODE) && defined(KLUDGELINEMODE) 490 /* 491 * This telnetd implementation does not really 492 * support timing marks, it just uses them to 493 * support the kludge linemode stuff. If we 494 * receive a will or wont TM in response to our 495 * do TM request that may have been sent to 496 * determine kludge linemode support, process 497 * it, otherwise TM should get a negative 498 * response back. 499 */ 500 /* 501 * Handle the linemode kludge stuff. 502 * If we are not currently supporting any 503 * linemode at all, then we assume that this 504 * is the client telling us to use kludge 505 * linemode in response to our query. Set the 506 * linemode type that is to be supported, note 507 * that the client wishes to use linemode, and 508 * eat the will TM as though it never arrived. 509 */ 510 if (lmodetype < KLUDGE_LINEMODE) { 511 lmodetype = KLUDGE_LINEMODE; 512 clientstat(TELOPT_LINEMODE, WILL, 0); 513 send_wont(TELOPT_SGA, 1); 514 } else if (lmodetype == NO_AUTOKLUDGE) { 515 lmodetype = KLUDGE_OK; 516 } 517 #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ 518 /* 519 * We never respond to a WILL TM, and 520 * we leave the state WONT. 521 */ 522 return; 523 524 case TELOPT_LFLOW: 525 /* 526 * If we are going to support flow control 527 * option, then don't worry peer that we can't 528 * change the flow control characters. 529 */ 530 slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS; 531 slctab[SLC_XON].defset.flag |= SLC_DEFAULT; 532 slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS; 533 slctab[SLC_XOFF].defset.flag |= SLC_DEFAULT; 534 /* FALLTHROUGH */ 535 case TELOPT_TTYPE: 536 case TELOPT_SGA: 537 case TELOPT_NAWS: 538 case TELOPT_TSPEED: 539 case TELOPT_XDISPLOC: 540 case TELOPT_NEW_ENVIRON: 541 case TELOPT_OLD_ENVIRON: 542 changeok++; 543 break; 544 545 #ifdef LINEMODE 546 case TELOPT_LINEMODE: 547 # ifdef KLUDGELINEMODE 548 /* 549 * Note client's desire to use linemode. 550 */ 551 lmodetype = REAL_LINEMODE; 552 # endif /* KLUDGELINEMODE */ 553 func = doclientstat; 554 changeok++; 555 break; 556 #endif /* LINEMODE */ 557 558 #ifdef AUTHENTICATION 559 case TELOPT_AUTHENTICATION: 560 func = auth_request; 561 changeok++; 562 break; 563 #endif 564 565 #ifdef ENCRYPTION 566 case TELOPT_ENCRYPT: 567 func = encrypt_send_support; 568 changeok++; 569 break; 570 #endif /* ENCRYPTION */ 571 572 default: 573 break; 574 } 575 if (changeok) { 576 set_his_want_state_will(option); 577 send_do(option, 0); 578 } else { 579 do_dont_resp[option]++; 580 send_dont(option, 0); 581 } 582 } else { 583 /* 584 * Option processing that should happen when 585 * we receive conformation of a change in 586 * state that we had requested. 587 */ 588 switch (option) { 589 case TELOPT_ECHO: 590 not42 = 0; /* looks like a 4.2 system */ 591 /* 592 * Egads, he responded "WILL ECHO". Turn 593 * it off right now! 594 */ 595 send_dont(option, 1); 596 /* 597 * "WILL ECHO". Kludge upon kludge! 598 * A 4.2 client is now echoing user input at 599 * the tty. This is probably undesireable and 600 * it should be stopped. The client will 601 * respond WONT TM to the DO TM that we send to 602 * check for kludge linemode. When the WONT TM 603 * arrives, linemode will be turned off and a 604 * change propogated to the pty. This change 605 * will cause us to process the new pty state 606 * in localstat(), which will notice that 607 * linemode is off and send a WILL ECHO 608 * so that we are properly in character mode and 609 * all is well. 610 */ 611 break; 612 #ifdef LINEMODE 613 case TELOPT_LINEMODE: 614 # ifdef KLUDGELINEMODE 615 /* 616 * Note client's desire to use linemode. 617 */ 618 lmodetype = REAL_LINEMODE; 619 # endif /* KLUDGELINEMODE */ 620 func = doclientstat; 621 break; 622 #endif /* LINEMODE */ 623 624 #ifdef AUTHENTICATION 625 case TELOPT_AUTHENTICATION: 626 func = auth_request; 627 break; 628 #endif 629 630 #ifdef ENCRYPTION 631 case TELOPT_ENCRYPT: 632 func = encrypt_send_support; 633 break; 634 #endif /* ENCRYPTION */ 635 636 case TELOPT_LFLOW: 637 func = flowstat; 638 break; 639 } 640 } 641 } 642 set_his_state_will(option); 643 if (func) 644 (*func)(); 645 } /* end of willoption */ 646 647 void 648 send_dont(int option, int init) 649 { 650 if (init) { 651 if ((do_dont_resp[option] == 0 && his_state_is_wont(option)) || 652 his_want_state_is_wont(option)) 653 return; 654 set_his_want_state_wont(option); 655 do_dont_resp[option]++; 656 } 657 (void) output_data("%c%c%c", IAC, DONT, option); 658 659 DIAG(TD_OPTIONS, printoption("td: send dont", option)); 660 } 661 662 void 663 wontoption(int option) 664 { 665 /* 666 * Process client input. 667 */ 668 669 DIAG(TD_OPTIONS, printoption("td: recv wont", option)); 670 671 if (do_dont_resp[option]) { 672 do_dont_resp[option]--; 673 if (do_dont_resp[option] && his_state_is_wont(option)) 674 do_dont_resp[option]--; 675 } 676 if (do_dont_resp[option] == 0) { 677 if (his_want_state_is_will(option)) { 678 /* it is always ok to change to negative state */ 679 switch (option) { 680 case TELOPT_ECHO: 681 not42 = 1; /* doesn't seem to be a 4.2 system */ 682 break; 683 684 case TELOPT_BINARY: 685 init_termbuf(); 686 tty_binaryin(0); 687 set_termbuf(); 688 break; 689 690 #ifdef LINEMODE 691 case TELOPT_LINEMODE: 692 # ifdef KLUDGELINEMODE 693 /* 694 * If real linemode is supported, then client is 695 * asking to turn linemode off. 696 */ 697 if (lmodetype != REAL_LINEMODE) 698 break; 699 /* XXX double-check this --thorpej */ 700 lmodetype = KLUDGE_LINEMODE; 701 # endif /* KLUDGELINEMODE */ 702 clientstat(TELOPT_LINEMODE, WONT, 0); 703 break; 704 #endif /* LINEMODE */ 705 706 case TELOPT_TM: 707 /* 708 * If we get a WONT TM, and had sent a DO TM, 709 * don't respond with a DONT TM, just leave it 710 * as is. Short circut the state machine to 711 * achieve this. 712 */ 713 set_his_want_state_wont(TELOPT_TM); 714 return; 715 716 case TELOPT_LFLOW: 717 /* 718 * If we are not going to support flow control 719 * option, then let peer know that we can't 720 * change the flow control characters. 721 */ 722 slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS; 723 slctab[SLC_XON].defset.flag |= SLC_CANTCHANGE; 724 slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS; 725 slctab[SLC_XOFF].defset.flag |= SLC_CANTCHANGE; 726 break; 727 728 #ifdef AUTHENTICATION 729 case TELOPT_AUTHENTICATION: 730 auth_finished(0, AUTH_REJECT); 731 break; 732 #endif 733 734 /* 735 * For options that we might spin waiting for 736 * sub-negotiation, if the client turns off the 737 * option rather than responding to the request, 738 * we have to treat it here as if we got a response 739 * to the sub-negotiation, (by updating the timers) 740 * so that we'll break out of the loop. 741 */ 742 case TELOPT_TTYPE: 743 settimer(ttypesubopt); 744 break; 745 746 case TELOPT_TSPEED: 747 settimer(tspeedsubopt); 748 break; 749 750 case TELOPT_XDISPLOC: 751 settimer(xdisplocsubopt); 752 break; 753 754 case TELOPT_OLD_ENVIRON: 755 settimer(oenvironsubopt); 756 break; 757 758 case TELOPT_NEW_ENVIRON: 759 settimer(environsubopt); 760 break; 761 762 default: 763 break; 764 } 765 set_his_want_state_wont(option); 766 if (his_state_is_will(option)) 767 send_dont(option, 0); 768 } else { 769 switch (option) { 770 case TELOPT_TM: 771 #if defined(LINEMODE) && defined(KLUDGELINEMODE) 772 if (lmodetype < NO_AUTOKLUDGE) { 773 lmodetype = NO_LINEMODE; 774 clientstat(TELOPT_LINEMODE, WONT, 0); 775 send_will(TELOPT_SGA, 1); 776 send_will(TELOPT_ECHO, 1); 777 } 778 #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ 779 break; 780 781 #ifdef AUTHENTICATION 782 case TELOPT_AUTHENTICATION: 783 auth_finished(0, AUTH_REJECT); 784 break; 785 #endif 786 default: 787 break; 788 } 789 } 790 } 791 set_his_state_wont(option); 792 793 } /* end of wontoption */ 794 795 void 796 send_will(int option, int init) 797 { 798 if (init) { 799 if ((will_wont_resp[option] == 0 && my_state_is_will(option))|| 800 my_want_state_is_will(option)) 801 return; 802 set_my_want_state_will(option); 803 will_wont_resp[option]++; 804 } 805 (void) output_data("%c%c%c", IAC, WILL, option); 806 807 DIAG(TD_OPTIONS, printoption("td: send will", option)); 808 } 809 810 #if !defined(LINEMODE) || !defined(KLUDGELINEMODE) 811 /* 812 * When we get a DONT SGA, we will try once to turn it 813 * back on. If the other side responds DONT SGA, we 814 * leave it at that. This is so that when we talk to 815 * clients that understand KLUDGELINEMODE but not LINEMODE, 816 * we'll keep them in char-at-a-time mode. 817 */ 818 int turn_on_sga = 0; 819 #endif 820 821 void 822 dooption(int option) 823 { 824 int changeok = 0; 825 826 /* 827 * Process client input. 828 */ 829 830 DIAG(TD_OPTIONS, printoption("td: recv do", option)); 831 832 if (will_wont_resp[option]) { 833 will_wont_resp[option]--; 834 if (will_wont_resp[option] && my_state_is_will(option)) 835 will_wont_resp[option]--; 836 } 837 if ((will_wont_resp[option] == 0) && (my_want_state_is_wont(option))) { 838 switch (option) { 839 case TELOPT_ECHO: 840 #ifdef LINEMODE 841 # ifdef KLUDGELINEMODE 842 if (lmodetype == NO_LINEMODE) 843 # else 844 if (his_state_is_wont(TELOPT_LINEMODE)) 845 # endif 846 #endif 847 { 848 init_termbuf(); 849 tty_setecho(1); 850 set_termbuf(); 851 } 852 changeok++; 853 break; 854 855 case TELOPT_BINARY: 856 init_termbuf(); 857 tty_binaryout(1); 858 set_termbuf(); 859 changeok++; 860 break; 861 862 case TELOPT_SGA: 863 #if defined(LINEMODE) && defined(KLUDGELINEMODE) 864 /* 865 * If kludge linemode is in use, then we must 866 * process an incoming do SGA for linemode 867 * purposes. 868 */ 869 if (lmodetype == KLUDGE_LINEMODE) { 870 /* 871 * Receipt of "do SGA" in kludge 872 * linemode is the peer asking us to 873 * turn off linemode. Make note of 874 * the request. 875 */ 876 clientstat(TELOPT_LINEMODE, WONT, 0); 877 /* 878 * If linemode did not get turned off 879 * then don't tell peer that we did. 880 * Breaking here forces a wont SGA to 881 * be returned. 882 */ 883 if (linemode) 884 break; 885 } 886 #else 887 turn_on_sga = 0; 888 #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ 889 changeok++; 890 break; 891 892 case TELOPT_STATUS: 893 changeok++; 894 break; 895 896 case TELOPT_TM: 897 /* 898 * Special case for TM. We send a WILL, but 899 * pretend we sent a WONT. 900 */ 901 send_will(option, 0); 902 set_my_want_state_wont(option); 903 set_my_state_wont(option); 904 return; 905 906 case TELOPT_LOGOUT: 907 /* 908 * When we get a LOGOUT option, respond 909 * with a WILL LOGOUT, make sure that 910 * it gets written out to the network, 911 * and then just go away... 912 */ 913 set_my_want_state_will(TELOPT_LOGOUT); 914 send_will(TELOPT_LOGOUT, 0); 915 set_my_state_will(TELOPT_LOGOUT); 916 (void)netflush(); 917 cleanup(0); 918 /* NOT REACHED */ 919 break; 920 921 #ifdef ENCRYPTION 922 case TELOPT_ENCRYPT: 923 changeok++; 924 break; 925 #endif /* ENCRYPTION */ 926 927 case TELOPT_LINEMODE: 928 case TELOPT_TTYPE: 929 case TELOPT_NAWS: 930 case TELOPT_TSPEED: 931 case TELOPT_LFLOW: 932 case TELOPT_XDISPLOC: 933 case TELOPT_OLD_ENVIRON: 934 default: 935 break; 936 } 937 if (changeok) { 938 set_my_want_state_will(option); 939 send_will(option, 0); 940 } else { 941 will_wont_resp[option]++; 942 send_wont(option, 0); 943 } 944 } 945 set_my_state_will(option); 946 947 } /* end of dooption */ 948 949 void 950 send_wont(int option, int init) 951 { 952 if (init) { 953 if ((will_wont_resp[option] == 0 && my_state_is_wont(option)) || 954 my_want_state_is_wont(option)) 955 return; 956 set_my_want_state_wont(option); 957 will_wont_resp[option]++; 958 } 959 (void) output_data("%c%c%c", IAC, WONT, option); 960 961 DIAG(TD_OPTIONS, printoption("td: send wont", option)); 962 } 963 964 void 965 dontoption(int option) 966 { 967 /* 968 * Process client input. 969 */ 970 971 972 DIAG(TD_OPTIONS, printoption("td: recv dont", option)); 973 974 if (will_wont_resp[option]) { 975 will_wont_resp[option]--; 976 if (will_wont_resp[option] && my_state_is_wont(option)) 977 will_wont_resp[option]--; 978 } 979 if ((will_wont_resp[option] == 0) && (my_want_state_is_will(option))) { 980 switch (option) { 981 case TELOPT_BINARY: 982 init_termbuf(); 983 tty_binaryout(0); 984 set_termbuf(); 985 break; 986 987 case TELOPT_ECHO: /* we should stop echoing */ 988 #ifdef LINEMODE 989 # ifdef KLUDGELINEMODE 990 if ((lmodetype != REAL_LINEMODE) && 991 (lmodetype != KLUDGE_LINEMODE)) 992 # else 993 if (his_state_is_wont(TELOPT_LINEMODE)) 994 # endif 995 #endif 996 { 997 init_termbuf(); 998 tty_setecho(0); 999 set_termbuf(); 1000 } 1001 break; 1002 1003 case TELOPT_SGA: 1004 #if defined(LINEMODE) && defined(KLUDGELINEMODE) 1005 /* 1006 * If kludge linemode is in use, then we 1007 * must process an incoming do SGA for 1008 * linemode purposes. 1009 */ 1010 if ((lmodetype == KLUDGE_LINEMODE) || 1011 (lmodetype == KLUDGE_OK)) { 1012 /* 1013 * The client is asking us to turn 1014 * linemode on. 1015 */ 1016 lmodetype = KLUDGE_LINEMODE; 1017 clientstat(TELOPT_LINEMODE, WILL, 0); 1018 /* 1019 * If we did not turn line mode on, 1020 * then what do we say? Will SGA? 1021 * This violates design of telnet. 1022 * Gross. Very Gross. 1023 */ 1024 } 1025 break; 1026 #else 1027 set_my_want_state_wont(option); 1028 if (my_state_is_will(option)) 1029 send_wont(option, 0); 1030 set_my_state_wont(option); 1031 if (turn_on_sga ^= 1) 1032 send_will(option, 1); 1033 return; 1034 #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ 1035 1036 default: 1037 break; 1038 } 1039 1040 set_my_want_state_wont(option); 1041 if (my_state_is_will(option)) 1042 send_wont(option, 0); 1043 } 1044 set_my_state_wont(option); 1045 1046 } /* end of dontoption */ 1047 1048 #ifdef ENV_HACK 1049 int env_ovar = -1; 1050 int env_ovalue = -1; 1051 #else /* ENV_HACK */ 1052 # define env_ovar OLD_ENV_VAR 1053 # define env_ovalue OLD_ENV_VALUE 1054 #endif /* ENV_HACK */ 1055 1056 /* envvarok(char*) */ 1057 /* check that variable is safe to pass to login or shell */ 1058 static int 1059 envvarok(char *varp) 1060 { 1061 1062 if (strcmp(varp, "TERMCAP") && /* to prevent a security hole */ 1063 strcmp(varp, "TERMINFO") && /* with tgetent */ 1064 strcmp(varp, "TERMPATH") && 1065 strcmp(varp, "HOME") && /* to prevent the tegetent bug */ 1066 strncmp(varp, "LD_", strlen("LD_")) && /* most systems */ 1067 strncmp(varp, "_RLD_", strlen("_RLD_")) && /* IRIX */ 1068 strcmp(varp, "LIBPATH") && /* AIX */ 1069 strcmp(varp, "ENV") && 1070 strcmp(varp, "BASH_ENV") && 1071 strcmp(varp, "IFS") && 1072 strncmp(varp, "KRB5", strlen("KRB5")) && /* Krb5 */ 1073 /* 1074 * The above case is a catch-all for now. Here are some of 1075 * the specific ones we must avoid passing, at least until 1076 * we can prove it can be done safely. Keep this list 1077 * around un case someone wants to remove the catch-all. 1078 */ 1079 strcmp(varp, "KRB5_CONFIG") && /* Krb5 */ 1080 strcmp(varp, "KRB5CCNAME") && /* Krb5 */ 1081 strcmp(varp, "KRB5_KTNAME") && /* Krb5 */ 1082 strcmp(varp, "KRBTKFILE") && /* Krb4 */ 1083 strcmp(varp, "KRB_CONF") && /* CNS 4 */ 1084 strcmp(varp, "KRB_REALMS") && /* CNS 4 */ 1085 strcmp(varp, "RESOLV_HOST_CONF")) /* Linux */ 1086 return (1); 1087 else { 1088 syslog(LOG_INFO, "Rejected the attempt to modify the " 1089 "environment variable \"%s\"", varp); 1090 return (0); 1091 } 1092 } 1093 1094 /* 1095 * suboption() 1096 * 1097 * Look at the sub-option buffer, and try to be helpful to the other 1098 * side. 1099 * 1100 * Currently we recognize: 1101 * 1102 * Terminal type is 1103 * Linemode 1104 * Window size 1105 * Terminal speed 1106 */ 1107 void 1108 suboption(void) 1109 { 1110 int subchar; 1111 1112 DIAG(TD_OPTIONS, {netflush(); printsub('<', subpointer, SB_LEN()+2);}); 1113 1114 subchar = SB_GET(); 1115 switch (subchar) { 1116 case TELOPT_TSPEED: { 1117 int xspeed, rspeed; 1118 1119 if (his_state_is_wont(TELOPT_TSPEED)) /* Ignore if option disabled */ 1120 break; 1121 1122 settimer(tspeedsubopt); 1123 1124 if (SB_EOF() || SB_GET() != TELQUAL_IS) 1125 return; 1126 1127 xspeed = atoi((char *)subpointer); 1128 1129 while (SB_GET() != ',' && !SB_EOF()); 1130 if (SB_EOF()) 1131 return; 1132 1133 rspeed = atoi((char *)subpointer); 1134 clientstat(TELOPT_TSPEED, xspeed, rspeed); 1135 1136 break; 1137 1138 } /* end of case TELOPT_TSPEED */ 1139 1140 case TELOPT_TTYPE: { /* Yaaaay! */ 1141 char *p; 1142 1143 if (his_state_is_wont(TELOPT_TTYPE)) /* Ignore if option disabled */ 1144 break; 1145 settimer(ttypesubopt); 1146 1147 if (SB_EOF() || SB_GET() != TELQUAL_IS) { 1148 return; /* ??? XXX but, this is the most robust */ 1149 } 1150 1151 p = terminaltype; 1152 1153 while ((p < (terminaltype + sizeof terminaltype-1)) && 1154 !SB_EOF()) { 1155 int c; 1156 1157 c = SB_GET(); 1158 if (isupper(c)) { 1159 c = tolower(c); 1160 } 1161 *p++ = c; /* accumulate name */ 1162 } 1163 *p = 0; 1164 break; 1165 } /* end of case TELOPT_TTYPE */ 1166 1167 case TELOPT_NAWS: { 1168 int xwinsize, ywinsize; 1169 1170 if (his_state_is_wont(TELOPT_NAWS)) /* Ignore if option disabled */ 1171 break; 1172 1173 if (SB_EOF()) 1174 return; 1175 xwinsize = SB_GET() << 8; 1176 if (SB_EOF()) 1177 return; 1178 xwinsize |= SB_GET(); 1179 if (SB_EOF()) 1180 return; 1181 ywinsize = SB_GET() << 8; 1182 if (SB_EOF()) 1183 return; 1184 ywinsize |= SB_GET(); 1185 clientstat(TELOPT_NAWS, xwinsize, ywinsize); 1186 1187 break; 1188 1189 } /* end of case TELOPT_NAWS */ 1190 1191 #ifdef LINEMODE 1192 case TELOPT_LINEMODE: { 1193 int request; 1194 1195 if (his_state_is_wont(TELOPT_LINEMODE)) /* Ignore if option disabled */ 1196 break; 1197 /* 1198 * Process linemode suboptions. 1199 */ 1200 if (SB_EOF()) 1201 break; /* garbage was sent */ 1202 request = SB_GET(); /* get will/wont */ 1203 1204 if (SB_EOF()) 1205 break; /* another garbage check */ 1206 1207 if (request == LM_SLC) { /* SLC is not preceded by WILL or WONT */ 1208 /* 1209 * Process suboption buffer of slc's 1210 */ 1211 start_slc(1); 1212 do_opt_slc(subpointer, SB_LEN()); 1213 (void) end_slc(0); 1214 break; 1215 } else if (request == LM_MODE) { 1216 if (SB_EOF()) 1217 return; 1218 useeditmode = SB_GET(); /* get mode flag */ 1219 clientstat(LM_MODE, 0, 0); 1220 break; 1221 } 1222 1223 if (SB_EOF()) 1224 break; 1225 switch (SB_GET()) { /* what suboption? */ 1226 case LM_FORWARDMASK: 1227 /* 1228 * According to spec, only server can send request for 1229 * forwardmask, and client can only return a positive response. 1230 * So don't worry about it. 1231 */ 1232 1233 default: 1234 break; 1235 } 1236 break; 1237 } /* end of case TELOPT_LINEMODE */ 1238 #endif 1239 case TELOPT_STATUS: { 1240 int mode; 1241 1242 if (SB_EOF()) 1243 break; 1244 mode = SB_GET(); 1245 switch (mode) { 1246 case TELQUAL_SEND: 1247 if (my_state_is_will(TELOPT_STATUS)) 1248 send_status(); 1249 break; 1250 1251 case TELQUAL_IS: 1252 break; 1253 1254 default: 1255 break; 1256 } 1257 break; 1258 } /* end of case TELOPT_STATUS */ 1259 1260 case TELOPT_XDISPLOC: { 1261 if (SB_EOF() || SB_GET() != TELQUAL_IS) 1262 return; 1263 settimer(xdisplocsubopt); 1264 subpointer[SB_LEN()] = '\0'; 1265 (void)setenv("DISPLAY", (char *)subpointer, 1); 1266 break; 1267 } /* end of case TELOPT_XDISPLOC */ 1268 1269 case TELOPT_NEW_ENVIRON: 1270 case TELOPT_OLD_ENVIRON: { 1271 int c; 1272 char *cp, *varp, *valp; 1273 1274 if (SB_EOF()) 1275 return; 1276 c = SB_GET(); 1277 if (c == TELQUAL_IS) { 1278 if (subchar == TELOPT_OLD_ENVIRON) 1279 settimer(oenvironsubopt); 1280 else 1281 settimer(environsubopt); 1282 } else if (c != TELQUAL_INFO) { 1283 return; 1284 } 1285 1286 if (subchar == TELOPT_NEW_ENVIRON) { 1287 while (!SB_EOF()) { 1288 c = SB_GET(); 1289 if ((c == NEW_ENV_VAR) || (c == ENV_USERVAR)) 1290 break; 1291 } 1292 } else 1293 { 1294 #ifdef ENV_HACK 1295 /* 1296 * We only want to do this if we haven't already decided 1297 * whether or not the other side has its VALUE and VAR 1298 * reversed. 1299 */ 1300 if (env_ovar < 0) { 1301 int last = -1; /* invalid value */ 1302 int empty = 0; 1303 int got_var = 0, got_value = 0, got_uservar = 0; 1304 1305 /* 1306 * The other side might have its VALUE and VAR values 1307 * reversed. To be interoperable, we need to determine 1308 * which way it is. If the first recognized character 1309 * is a VAR or VALUE, then that will tell us what 1310 * type of client it is. If the fist recognized 1311 * character is a USERVAR, then we continue scanning 1312 * the suboption looking for two consecutive 1313 * VAR or VALUE fields. We should not get two 1314 * consecutive VALUE fields, so finding two 1315 * consecutive VALUE or VAR fields will tell us 1316 * what the client is. 1317 */ 1318 SB_SAVE(); 1319 while (!SB_EOF()) { 1320 c = SB_GET(); 1321 switch(c) { 1322 case OLD_ENV_VAR: 1323 if (last < 0 || last == OLD_ENV_VAR 1324 || (empty && (last == OLD_ENV_VALUE))) 1325 goto env_ovar_ok; 1326 got_var++; 1327 last = OLD_ENV_VAR; 1328 break; 1329 case OLD_ENV_VALUE: 1330 if (last < 0 || last == OLD_ENV_VALUE 1331 || (empty && (last == OLD_ENV_VAR))) 1332 goto env_ovar_wrong; 1333 got_value++; 1334 last = OLD_ENV_VALUE; 1335 break; 1336 case ENV_USERVAR: 1337 /* count strings of USERVAR as one */ 1338 if (last != ENV_USERVAR) 1339 got_uservar++; 1340 if (empty) { 1341 if (last == OLD_ENV_VALUE) 1342 goto env_ovar_ok; 1343 if (last == OLD_ENV_VAR) 1344 goto env_ovar_wrong; 1345 } 1346 last = ENV_USERVAR; 1347 break; 1348 case ENV_ESC: 1349 if (!SB_EOF()) 1350 c = SB_GET(); 1351 /* FALL THROUGH */ 1352 default: 1353 empty = 0; 1354 continue; 1355 } 1356 empty = 1; 1357 } 1358 if (empty) { 1359 if (last == OLD_ENV_VALUE) 1360 goto env_ovar_ok; 1361 if (last == OLD_ENV_VAR) 1362 goto env_ovar_wrong; 1363 } 1364 /* 1365 * Ok, the first thing was a USERVAR, and there 1366 * are not two consecutive VAR or VALUE commands, 1367 * and none of the VAR or VALUE commands are empty. 1368 * If the client has sent us a well-formed option, 1369 * then the number of VALUEs received should always 1370 * be less than or equal to the number of VARs and 1371 * USERVARs received. 1372 * 1373 * If we got exactly as many VALUEs as VARs and 1374 * USERVARs, the client has the same definitions. 1375 * 1376 * If we got exactly as many VARs as VALUEs and 1377 * USERVARS, the client has reversed definitions. 1378 */ 1379 if (got_uservar + got_var == got_value) { 1380 env_ovar_ok: 1381 env_ovar = OLD_ENV_VAR; 1382 env_ovalue = OLD_ENV_VALUE; 1383 } else if (got_uservar + got_value == got_var) { 1384 env_ovar_wrong: 1385 env_ovar = OLD_ENV_VALUE; 1386 env_ovalue = OLD_ENV_VAR; 1387 DIAG(TD_OPTIONS, {output_data( 1388 "ENVIRON VALUE and VAR are reversed!\r\n");}); 1389 1390 } 1391 } 1392 SB_RESTORE(); 1393 #endif 1394 1395 while (!SB_EOF()) { 1396 c = SB_GET(); 1397 if ((c == env_ovar) || (c == ENV_USERVAR)) 1398 break; 1399 } 1400 } 1401 1402 if (SB_EOF()) 1403 return; 1404 1405 cp = varp = (char *)subpointer; 1406 valp = 0; 1407 1408 while (!SB_EOF()) { 1409 c = SB_GET(); 1410 if (subchar == TELOPT_OLD_ENVIRON) { 1411 if (c == env_ovar) 1412 c = NEW_ENV_VAR; 1413 else if (c == env_ovalue) 1414 c = NEW_ENV_VALUE; 1415 } 1416 switch (c) { 1417 1418 case NEW_ENV_VALUE: 1419 *cp = '\0'; 1420 cp = valp = (char *)subpointer; 1421 break; 1422 1423 case NEW_ENV_VAR: 1424 case ENV_USERVAR: 1425 *cp = '\0'; 1426 if (envvarok(varp)) { 1427 if (valp) 1428 (void)setenv(varp, valp, 1); 1429 else 1430 unsetenv(varp); 1431 } 1432 cp = varp = (char *)subpointer; 1433 valp = 0; 1434 break; 1435 1436 case ENV_ESC: 1437 if (SB_EOF()) 1438 break; 1439 c = SB_GET(); 1440 /* FALL THROUGH */ 1441 default: 1442 *cp++ = c; 1443 break; 1444 } 1445 } 1446 *cp = '\0'; 1447 if (envvarok(varp)) { 1448 if (valp) 1449 (void)setenv(varp, valp, 1); 1450 else 1451 unsetenv(varp); 1452 } 1453 break; 1454 } /* end of case TELOPT_NEW_ENVIRON */ 1455 #ifdef AUTHENTICATION 1456 case TELOPT_AUTHENTICATION: 1457 if (SB_EOF()) 1458 break; 1459 switch(SB_GET()) { 1460 case TELQUAL_SEND: 1461 case TELQUAL_REPLY: 1462 /* 1463 * These are sent by us and cannot be sent by 1464 * the client. 1465 */ 1466 break; 1467 case TELQUAL_IS: 1468 auth_is(subpointer, SB_LEN()); 1469 break; 1470 case TELQUAL_NAME: 1471 auth_name(subpointer, SB_LEN()); 1472 break; 1473 } 1474 break; 1475 #endif 1476 #ifdef ENCRYPTION 1477 case TELOPT_ENCRYPT: 1478 if (SB_EOF()) 1479 break; 1480 switch(SB_GET()) { 1481 case ENCRYPT_SUPPORT: 1482 encrypt_support(subpointer, SB_LEN()); 1483 break; 1484 case ENCRYPT_IS: 1485 encrypt_is(subpointer, SB_LEN()); 1486 break; 1487 case ENCRYPT_REPLY: 1488 encrypt_reply(subpointer, SB_LEN()); 1489 break; 1490 case ENCRYPT_START: 1491 encrypt_start(subpointer, SB_LEN()); 1492 break; 1493 case ENCRYPT_END: 1494 encrypt_end(); 1495 break; 1496 case ENCRYPT_REQSTART: 1497 encrypt_request_start(subpointer, SB_LEN()); 1498 break; 1499 case ENCRYPT_REQEND: 1500 /* 1501 * We can always send an REQEND so that we cannot 1502 * get stuck encrypting. We should only get this 1503 * if we have been able to get in the correct mode 1504 * anyhow. 1505 */ 1506 encrypt_request_end(); 1507 break; 1508 case ENCRYPT_ENC_KEYID: 1509 encrypt_enc_keyid(subpointer, SB_LEN()); 1510 break; 1511 case ENCRYPT_DEC_KEYID: 1512 encrypt_dec_keyid(subpointer, SB_LEN()); 1513 break; 1514 default: 1515 break; 1516 } 1517 break; 1518 #endif /* ENCRYPTION */ 1519 1520 default: 1521 break; 1522 } /* end of switch */ 1523 1524 } /* end of suboption */ 1525 1526 #ifdef LINEMODE 1527 void 1528 doclientstat(void) 1529 { 1530 clientstat(TELOPT_LINEMODE, WILL, 0); 1531 } 1532 #endif /* LINEMODE */ 1533 1534 void 1535 send_status(void) 1536 { 1537 #define ADD(c) \ 1538 do { \ 1539 if (ep > ncp) \ 1540 *ncp++ = c; \ 1541 else \ 1542 goto trunc; \ 1543 } while (0) 1544 #define ADD_DATA(c) \ 1545 do { \ 1546 ADD(c); if (c == SE || c == IAC) ADD(c); \ 1547 } while (0) 1548 1549 unsigned char statusbuf[256]; 1550 unsigned char *ep; 1551 unsigned char *ncp; 1552 unsigned char i; 1553 1554 ncp = statusbuf; 1555 ep = statusbuf + sizeof(statusbuf); 1556 1557 netflush(); /* get rid of anything waiting to go out */ 1558 1559 ADD(IAC); 1560 ADD(SB); 1561 ADD(TELOPT_STATUS); 1562 ADD(TELQUAL_IS); 1563 1564 /* 1565 * We check the want_state rather than the current state, 1566 * because if we received a DO/WILL for an option that we 1567 * don't support, and the other side didn't send a DONT/WONT 1568 * in response to our WONT/DONT, then the "state" will be 1569 * WILL/DO, and the "want_state" will be WONT/DONT. We 1570 * need to go by the latter. 1571 */ 1572 for (i = 0; i < (unsigned char)NTELOPTS; i++) { 1573 if (my_want_state_is_will(i)) { 1574 ADD(WILL); 1575 ADD_DATA(i); 1576 } 1577 if (his_want_state_is_will(i)) { 1578 ADD(DO); 1579 ADD_DATA(i); 1580 } 1581 } 1582 1583 if (his_want_state_is_will(TELOPT_LFLOW)) { 1584 ADD(SB); 1585 ADD(TELOPT_LFLOW); 1586 if (flowmode) { 1587 ADD(LFLOW_ON); 1588 } else { 1589 ADD(LFLOW_OFF); 1590 } 1591 ADD(SE); 1592 1593 if (restartany >= 0) { 1594 ADD(SB); 1595 ADD(TELOPT_LFLOW); 1596 if (restartany) { 1597 ADD(LFLOW_RESTART_ANY); 1598 } else { 1599 ADD(LFLOW_RESTART_XON); 1600 } 1601 ADD(SE); 1602 } 1603 } 1604 1605 #ifdef LINEMODE 1606 if (his_want_state_is_will(TELOPT_LINEMODE)) { 1607 unsigned char *cp, *cpe; 1608 int len; 1609 1610 ADD(SB); 1611 ADD(TELOPT_LINEMODE); 1612 ADD(LM_MODE); 1613 ADD_DATA(editmode); 1614 ADD(SE); 1615 1616 ADD(SB); 1617 ADD(TELOPT_LINEMODE); 1618 ADD(LM_SLC); 1619 start_slc(0); 1620 send_slc(); 1621 len = end_slc(&cp); 1622 for (cpe = cp + len; cp < cpe; cp++) 1623 ADD_DATA(*cp); 1624 ADD(SE); 1625 } 1626 #endif /* LINEMODE */ 1627 1628 ADD(IAC); 1629 ADD(SE); 1630 1631 writenet(statusbuf, ncp - statusbuf); 1632 netflush(); /* Send it on its way */ 1633 1634 DIAG(TD_OPTIONS, 1635 {printsub('>', statusbuf, ncp - statusbuf); netflush();}); 1636 return; 1637 1638 trunc: 1639 /* XXX bark? */ 1640 return; 1641 #undef ADD 1642 #undef ADD_DATA 1643 } 1644 1645 int 1646 output_data(const char *format, ...) 1647 { 1648 va_list args; 1649 size_t remaining, ret; 1650 1651 va_start(args, format); 1652 remaining = BUFSIZ - (nfrontp - netobuf); 1653 /* try a netflush() if the room is too low */ 1654 if (strlen(format) > remaining || BUFSIZ / 4 > remaining) { 1655 netflush(); 1656 remaining = BUFSIZ - (nfrontp - netobuf); 1657 } 1658 ret = vsnprintf(nfrontp, remaining, format, args); 1659 nfrontp += ((ret < remaining - 1) ? ret : remaining - 1); 1660 va_end(args); 1661 return ret; 1662 } 1663 1664 int 1665 output_datalen(const char *buf, size_t l) 1666 { 1667 size_t remaining; 1668 1669 remaining = BUFSIZ - (nfrontp - netobuf); 1670 if (remaining < l) { 1671 netflush(); 1672 remaining = BUFSIZ - (nfrontp - netobuf); 1673 } 1674 if (remaining < l) 1675 return -1; 1676 memmove(nfrontp, buf, l); 1677 nfrontp += l; 1678 return (int)l; 1679 } 1680