1 /* $NetBSD: state.c,v 1.30 2016/12/12 15:58:44 maya 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.30 2016/12/12 15:58:44 maya 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 case TELOPT_TTYPE: 535 case TELOPT_SGA: 536 case TELOPT_NAWS: 537 case TELOPT_TSPEED: 538 case TELOPT_XDISPLOC: 539 case TELOPT_NEW_ENVIRON: 540 case TELOPT_OLD_ENVIRON: 541 changeok++; 542 break; 543 544 #ifdef LINEMODE 545 case TELOPT_LINEMODE: 546 # ifdef KLUDGELINEMODE 547 /* 548 * Note client's desire to use linemode. 549 */ 550 lmodetype = REAL_LINEMODE; 551 # endif /* KLUDGELINEMODE */ 552 func = doclientstat; 553 changeok++; 554 break; 555 #endif /* LINEMODE */ 556 557 #ifdef AUTHENTICATION 558 case TELOPT_AUTHENTICATION: 559 func = auth_request; 560 changeok++; 561 break; 562 #endif 563 564 #ifdef ENCRYPTION 565 case TELOPT_ENCRYPT: 566 func = encrypt_send_support; 567 changeok++; 568 break; 569 #endif /* ENCRYPTION */ 570 571 default: 572 break; 573 } 574 if (changeok) { 575 set_his_want_state_will(option); 576 send_do(option, 0); 577 } else { 578 do_dont_resp[option]++; 579 send_dont(option, 0); 580 } 581 } else { 582 /* 583 * Option processing that should happen when 584 * we receive conformation of a change in 585 * state that we had requested. 586 */ 587 switch (option) { 588 case TELOPT_ECHO: 589 not42 = 0; /* looks like a 4.2 system */ 590 /* 591 * Egads, he responded "WILL ECHO". Turn 592 * it off right now! 593 */ 594 send_dont(option, 1); 595 /* 596 * "WILL ECHO". Kludge upon kludge! 597 * A 4.2 client is now echoing user input at 598 * the tty. This is probably undesireable and 599 * it should be stopped. The client will 600 * respond WONT TM to the DO TM that we send to 601 * check for kludge linemode. When the WONT TM 602 * arrives, linemode will be turned off and a 603 * change propogated to the pty. This change 604 * will cause us to process the new pty state 605 * in localstat(), which will notice that 606 * linemode is off and send a WILL ECHO 607 * so that we are properly in character mode and 608 * all is well. 609 */ 610 break; 611 #ifdef LINEMODE 612 case TELOPT_LINEMODE: 613 # ifdef KLUDGELINEMODE 614 /* 615 * Note client's desire to use linemode. 616 */ 617 lmodetype = REAL_LINEMODE; 618 # endif /* KLUDGELINEMODE */ 619 func = doclientstat; 620 break; 621 #endif /* LINEMODE */ 622 623 #ifdef AUTHENTICATION 624 case TELOPT_AUTHENTICATION: 625 func = auth_request; 626 break; 627 #endif 628 629 #ifdef ENCRYPTION 630 case TELOPT_ENCRYPT: 631 func = encrypt_send_support; 632 break; 633 #endif /* ENCRYPTION */ 634 635 case TELOPT_LFLOW: 636 func = flowstat; 637 break; 638 } 639 } 640 } 641 set_his_state_will(option); 642 if (func) 643 (*func)(); 644 } /* end of willoption */ 645 646 void 647 send_dont(int option, int init) 648 { 649 if (init) { 650 if ((do_dont_resp[option] == 0 && his_state_is_wont(option)) || 651 his_want_state_is_wont(option)) 652 return; 653 set_his_want_state_wont(option); 654 do_dont_resp[option]++; 655 } 656 (void) output_data("%c%c%c", IAC, DONT, option); 657 658 DIAG(TD_OPTIONS, printoption("td: send dont", option)); 659 } 660 661 void 662 wontoption(int option) 663 { 664 /* 665 * Process client input. 666 */ 667 668 DIAG(TD_OPTIONS, printoption("td: recv wont", option)); 669 670 if (do_dont_resp[option]) { 671 do_dont_resp[option]--; 672 if (do_dont_resp[option] && his_state_is_wont(option)) 673 do_dont_resp[option]--; 674 } 675 if (do_dont_resp[option] == 0) { 676 if (his_want_state_is_will(option)) { 677 /* it is always ok to change to negative state */ 678 switch (option) { 679 case TELOPT_ECHO: 680 not42 = 1; /* doesn't seem to be a 4.2 system */ 681 break; 682 683 case TELOPT_BINARY: 684 init_termbuf(); 685 tty_binaryin(0); 686 set_termbuf(); 687 break; 688 689 #ifdef LINEMODE 690 case TELOPT_LINEMODE: 691 # ifdef KLUDGELINEMODE 692 /* 693 * If real linemode is supported, then client is 694 * asking to turn linemode off. 695 */ 696 if (lmodetype != REAL_LINEMODE) 697 break; 698 /* XXX double-check this --thorpej */ 699 lmodetype = KLUDGE_LINEMODE; 700 # endif /* KLUDGELINEMODE */ 701 clientstat(TELOPT_LINEMODE, WONT, 0); 702 break; 703 #endif /* LINEMODE */ 704 705 case TELOPT_TM: 706 /* 707 * If we get a WONT TM, and had sent a DO TM, 708 * don't respond with a DONT TM, just leave it 709 * as is. Short circut the state machine to 710 * achieve this. 711 */ 712 set_his_want_state_wont(TELOPT_TM); 713 return; 714 715 case TELOPT_LFLOW: 716 /* 717 * If we are not going to support flow control 718 * option, then let peer know that we can't 719 * change the flow control characters. 720 */ 721 slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS; 722 slctab[SLC_XON].defset.flag |= SLC_CANTCHANGE; 723 slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS; 724 slctab[SLC_XOFF].defset.flag |= SLC_CANTCHANGE; 725 break; 726 727 #ifdef AUTHENTICATION 728 case TELOPT_AUTHENTICATION: 729 auth_finished(0, AUTH_REJECT); 730 break; 731 #endif 732 733 /* 734 * For options that we might spin waiting for 735 * sub-negotiation, if the client turns off the 736 * option rather than responding to the request, 737 * we have to treat it here as if we got a response 738 * to the sub-negotiation, (by updating the timers) 739 * so that we'll break out of the loop. 740 */ 741 case TELOPT_TTYPE: 742 settimer(ttypesubopt); 743 break; 744 745 case TELOPT_TSPEED: 746 settimer(tspeedsubopt); 747 break; 748 749 case TELOPT_XDISPLOC: 750 settimer(xdisplocsubopt); 751 break; 752 753 case TELOPT_OLD_ENVIRON: 754 settimer(oenvironsubopt); 755 break; 756 757 case TELOPT_NEW_ENVIRON: 758 settimer(environsubopt); 759 break; 760 761 default: 762 break; 763 } 764 set_his_want_state_wont(option); 765 if (his_state_is_will(option)) 766 send_dont(option, 0); 767 } else { 768 switch (option) { 769 case TELOPT_TM: 770 #if defined(LINEMODE) && defined(KLUDGELINEMODE) 771 if (lmodetype < NO_AUTOKLUDGE) { 772 lmodetype = NO_LINEMODE; 773 clientstat(TELOPT_LINEMODE, WONT, 0); 774 send_will(TELOPT_SGA, 1); 775 send_will(TELOPT_ECHO, 1); 776 } 777 #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ 778 break; 779 780 #ifdef AUTHENTICATION 781 case TELOPT_AUTHENTICATION: 782 auth_finished(0, AUTH_REJECT); 783 break; 784 #endif 785 default: 786 break; 787 } 788 } 789 } 790 set_his_state_wont(option); 791 792 } /* end of wontoption */ 793 794 void 795 send_will(int option, int init) 796 { 797 if (init) { 798 if ((will_wont_resp[option] == 0 && my_state_is_will(option))|| 799 my_want_state_is_will(option)) 800 return; 801 set_my_want_state_will(option); 802 will_wont_resp[option]++; 803 } 804 (void) output_data("%c%c%c", IAC, WILL, option); 805 806 DIAG(TD_OPTIONS, printoption("td: send will", option)); 807 } 808 809 #if !defined(LINEMODE) || !defined(KLUDGELINEMODE) 810 /* 811 * When we get a DONT SGA, we will try once to turn it 812 * back on. If the other side responds DONT SGA, we 813 * leave it at that. This is so that when we talk to 814 * clients that understand KLUDGELINEMODE but not LINEMODE, 815 * we'll keep them in char-at-a-time mode. 816 */ 817 int turn_on_sga = 0; 818 #endif 819 820 void 821 dooption(int option) 822 { 823 int changeok = 0; 824 825 /* 826 * Process client input. 827 */ 828 829 DIAG(TD_OPTIONS, printoption("td: recv do", option)); 830 831 if (will_wont_resp[option]) { 832 will_wont_resp[option]--; 833 if (will_wont_resp[option] && my_state_is_will(option)) 834 will_wont_resp[option]--; 835 } 836 if ((will_wont_resp[option] == 0) && (my_want_state_is_wont(option))) { 837 switch (option) { 838 case TELOPT_ECHO: 839 #ifdef LINEMODE 840 # ifdef KLUDGELINEMODE 841 if (lmodetype == NO_LINEMODE) 842 # else 843 if (his_state_is_wont(TELOPT_LINEMODE)) 844 # endif 845 #endif 846 { 847 init_termbuf(); 848 tty_setecho(1); 849 set_termbuf(); 850 } 851 changeok++; 852 break; 853 854 case TELOPT_BINARY: 855 init_termbuf(); 856 tty_binaryout(1); 857 set_termbuf(); 858 changeok++; 859 break; 860 861 case TELOPT_SGA: 862 #if defined(LINEMODE) && defined(KLUDGELINEMODE) 863 /* 864 * If kludge linemode is in use, then we must 865 * process an incoming do SGA for linemode 866 * purposes. 867 */ 868 if (lmodetype == KLUDGE_LINEMODE) { 869 /* 870 * Receipt of "do SGA" in kludge 871 * linemode is the peer asking us to 872 * turn off linemode. Make note of 873 * the request. 874 */ 875 clientstat(TELOPT_LINEMODE, WONT, 0); 876 /* 877 * If linemode did not get turned off 878 * then don't tell peer that we did. 879 * Breaking here forces a wont SGA to 880 * be returned. 881 */ 882 if (linemode) 883 break; 884 } 885 #else 886 turn_on_sga = 0; 887 #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ 888 changeok++; 889 break; 890 891 case TELOPT_STATUS: 892 changeok++; 893 break; 894 895 case TELOPT_TM: 896 /* 897 * Special case for TM. We send a WILL, but 898 * pretend we sent a WONT. 899 */ 900 send_will(option, 0); 901 set_my_want_state_wont(option); 902 set_my_state_wont(option); 903 return; 904 905 case TELOPT_LOGOUT: 906 /* 907 * When we get a LOGOUT option, respond 908 * with a WILL LOGOUT, make sure that 909 * it gets written out to the network, 910 * and then just go away... 911 */ 912 set_my_want_state_will(TELOPT_LOGOUT); 913 send_will(TELOPT_LOGOUT, 0); 914 set_my_state_will(TELOPT_LOGOUT); 915 (void)netflush(); 916 cleanup(0); 917 /* NOT REACHED */ 918 break; 919 920 #ifdef ENCRYPTION 921 case TELOPT_ENCRYPT: 922 changeok++; 923 break; 924 #endif /* ENCRYPTION */ 925 926 case TELOPT_LINEMODE: 927 case TELOPT_TTYPE: 928 case TELOPT_NAWS: 929 case TELOPT_TSPEED: 930 case TELOPT_LFLOW: 931 case TELOPT_XDISPLOC: 932 case TELOPT_OLD_ENVIRON: 933 default: 934 break; 935 } 936 if (changeok) { 937 set_my_want_state_will(option); 938 send_will(option, 0); 939 } else { 940 will_wont_resp[option]++; 941 send_wont(option, 0); 942 } 943 } 944 set_my_state_will(option); 945 946 } /* end of dooption */ 947 948 void 949 send_wont(int option, int init) 950 { 951 if (init) { 952 if ((will_wont_resp[option] == 0 && my_state_is_wont(option)) || 953 my_want_state_is_wont(option)) 954 return; 955 set_my_want_state_wont(option); 956 will_wont_resp[option]++; 957 } 958 (void) output_data("%c%c%c", IAC, WONT, option); 959 960 DIAG(TD_OPTIONS, printoption("td: send wont", option)); 961 } 962 963 void 964 dontoption(int option) 965 { 966 /* 967 * Process client input. 968 */ 969 970 971 DIAG(TD_OPTIONS, printoption("td: recv dont", option)); 972 973 if (will_wont_resp[option]) { 974 will_wont_resp[option]--; 975 if (will_wont_resp[option] && my_state_is_wont(option)) 976 will_wont_resp[option]--; 977 } 978 if ((will_wont_resp[option] == 0) && (my_want_state_is_will(option))) { 979 switch (option) { 980 case TELOPT_BINARY: 981 init_termbuf(); 982 tty_binaryout(0); 983 set_termbuf(); 984 break; 985 986 case TELOPT_ECHO: /* we should stop echoing */ 987 #ifdef LINEMODE 988 # ifdef KLUDGELINEMODE 989 if ((lmodetype != REAL_LINEMODE) && 990 (lmodetype != KLUDGE_LINEMODE)) 991 # else 992 if (his_state_is_wont(TELOPT_LINEMODE)) 993 # endif 994 #endif 995 { 996 init_termbuf(); 997 tty_setecho(0); 998 set_termbuf(); 999 } 1000 break; 1001 1002 case TELOPT_SGA: 1003 #if defined(LINEMODE) && defined(KLUDGELINEMODE) 1004 /* 1005 * If kludge linemode is in use, then we 1006 * must process an incoming do SGA for 1007 * linemode purposes. 1008 */ 1009 if ((lmodetype == KLUDGE_LINEMODE) || 1010 (lmodetype == KLUDGE_OK)) { 1011 /* 1012 * The client is asking us to turn 1013 * linemode on. 1014 */ 1015 lmodetype = KLUDGE_LINEMODE; 1016 clientstat(TELOPT_LINEMODE, WILL, 0); 1017 /* 1018 * If we did not turn line mode on, 1019 * then what do we say? Will SGA? 1020 * This violates design of telnet. 1021 * Gross. Very Gross. 1022 */ 1023 } 1024 break; 1025 #else 1026 set_my_want_state_wont(option); 1027 if (my_state_is_will(option)) 1028 send_wont(option, 0); 1029 set_my_state_wont(option); 1030 if (turn_on_sga ^= 1) 1031 send_will(option, 1); 1032 return; 1033 #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ 1034 1035 default: 1036 break; 1037 } 1038 1039 set_my_want_state_wont(option); 1040 if (my_state_is_will(option)) 1041 send_wont(option, 0); 1042 } 1043 set_my_state_wont(option); 1044 1045 } /* end of dontoption */ 1046 1047 #ifdef ENV_HACK 1048 int env_ovar = -1; 1049 int env_ovalue = -1; 1050 #else /* ENV_HACK */ 1051 # define env_ovar OLD_ENV_VAR 1052 # define env_ovalue OLD_ENV_VALUE 1053 #endif /* ENV_HACK */ 1054 1055 /* envvarok(char*) */ 1056 /* check that variable is safe to pass to login or shell */ 1057 static int 1058 envvarok(char *varp) 1059 { 1060 1061 if (strcmp(varp, "TERMCAP") && /* to prevent a security hole */ 1062 strcmp(varp, "TERMINFO") && /* with tgetent */ 1063 strcmp(varp, "TERMPATH") && 1064 strcmp(varp, "HOME") && /* to prevent the tegetent bug */ 1065 strncmp(varp, "LD_", strlen("LD_")) && /* most systems */ 1066 strncmp(varp, "_RLD_", strlen("_RLD_")) && /* IRIX */ 1067 strcmp(varp, "LIBPATH") && /* AIX */ 1068 strcmp(varp, "ENV") && 1069 strcmp(varp, "BASH_ENV") && 1070 strcmp(varp, "IFS") && 1071 strncmp(varp, "KRB5", strlen("KRB5")) && /* Krb5 */ 1072 /* 1073 * The above case is a catch-all for now. Here are some of 1074 * the specific ones we must avoid passing, at least until 1075 * we can prove it can be done safely. Keep this list 1076 * around un case someone wants to remove the catch-all. 1077 */ 1078 strcmp(varp, "KRB5_CONFIG") && /* Krb5 */ 1079 strcmp(varp, "KRB5CCNAME") && /* Krb5 */ 1080 strcmp(varp, "KRB5_KTNAME") && /* Krb5 */ 1081 strcmp(varp, "KRBTKFILE") && /* Krb4 */ 1082 strcmp(varp, "KRB_CONF") && /* CNS 4 */ 1083 strcmp(varp, "KRB_REALMS") && /* CNS 4 */ 1084 strcmp(varp, "RESOLV_HOST_CONF")) /* Linux */ 1085 return (1); 1086 else { 1087 syslog(LOG_INFO, "Rejected the attempt to modify the " 1088 "environment variable \"%s\"", varp); 1089 return (0); 1090 } 1091 } 1092 1093 /* 1094 * suboption() 1095 * 1096 * Look at the sub-option buffer, and try to be helpful to the other 1097 * side. 1098 * 1099 * Currently we recognize: 1100 * 1101 * Terminal type is 1102 * Linemode 1103 * Window size 1104 * Terminal speed 1105 */ 1106 void 1107 suboption(void) 1108 { 1109 int subchar; 1110 1111 DIAG(TD_OPTIONS, {netflush(); printsub('<', subpointer, SB_LEN()+2);}); 1112 1113 subchar = SB_GET(); 1114 switch (subchar) { 1115 case TELOPT_TSPEED: { 1116 int xspeed, rspeed; 1117 1118 if (his_state_is_wont(TELOPT_TSPEED)) /* Ignore if option disabled */ 1119 break; 1120 1121 settimer(tspeedsubopt); 1122 1123 if (SB_EOF() || SB_GET() != TELQUAL_IS) 1124 return; 1125 1126 xspeed = atoi((char *)subpointer); 1127 1128 while (SB_GET() != ',' && !SB_EOF()); 1129 if (SB_EOF()) 1130 return; 1131 1132 rspeed = atoi((char *)subpointer); 1133 clientstat(TELOPT_TSPEED, xspeed, rspeed); 1134 1135 break; 1136 1137 } /* end of case TELOPT_TSPEED */ 1138 1139 case TELOPT_TTYPE: { /* Yaaaay! */ 1140 char *p; 1141 1142 if (his_state_is_wont(TELOPT_TTYPE)) /* Ignore if option disabled */ 1143 break; 1144 settimer(ttypesubopt); 1145 1146 if (SB_EOF() || SB_GET() != TELQUAL_IS) { 1147 return; /* ??? XXX but, this is the most robust */ 1148 } 1149 1150 p = terminaltype; 1151 1152 while ((p < (terminaltype + sizeof terminaltype-1)) && 1153 !SB_EOF()) { 1154 int c; 1155 1156 c = SB_GET(); 1157 if (isupper(c)) { 1158 c = tolower(c); 1159 } 1160 *p++ = c; /* accumulate name */ 1161 } 1162 *p = 0; 1163 break; 1164 } /* end of case TELOPT_TTYPE */ 1165 1166 case TELOPT_NAWS: { 1167 int xwinsize, ywinsize; 1168 1169 if (his_state_is_wont(TELOPT_NAWS)) /* Ignore if option disabled */ 1170 break; 1171 1172 if (SB_EOF()) 1173 return; 1174 xwinsize = SB_GET() << 8; 1175 if (SB_EOF()) 1176 return; 1177 xwinsize |= SB_GET(); 1178 if (SB_EOF()) 1179 return; 1180 ywinsize = SB_GET() << 8; 1181 if (SB_EOF()) 1182 return; 1183 ywinsize |= SB_GET(); 1184 clientstat(TELOPT_NAWS, xwinsize, ywinsize); 1185 1186 break; 1187 1188 } /* end of case TELOPT_NAWS */ 1189 1190 #ifdef LINEMODE 1191 case TELOPT_LINEMODE: { 1192 int request; 1193 1194 if (his_state_is_wont(TELOPT_LINEMODE)) /* Ignore if option disabled */ 1195 break; 1196 /* 1197 * Process linemode suboptions. 1198 */ 1199 if (SB_EOF()) 1200 break; /* garbage was sent */ 1201 request = SB_GET(); /* get will/wont */ 1202 1203 if (SB_EOF()) 1204 break; /* another garbage check */ 1205 1206 if (request == LM_SLC) { /* SLC is not preceded by WILL or WONT */ 1207 /* 1208 * Process suboption buffer of slc's 1209 */ 1210 start_slc(1); 1211 do_opt_slc(subpointer, SB_LEN()); 1212 (void) end_slc(0); 1213 break; 1214 } else if (request == LM_MODE) { 1215 if (SB_EOF()) 1216 return; 1217 useeditmode = SB_GET(); /* get mode flag */ 1218 clientstat(LM_MODE, 0, 0); 1219 break; 1220 } 1221 1222 if (SB_EOF()) 1223 break; 1224 switch (SB_GET()) { /* what suboption? */ 1225 case LM_FORWARDMASK: 1226 /* 1227 * According to spec, only server can send request for 1228 * forwardmask, and client can only return a positive response. 1229 * So don't worry about it. 1230 */ 1231 1232 default: 1233 break; 1234 } 1235 break; 1236 } /* end of case TELOPT_LINEMODE */ 1237 #endif 1238 case TELOPT_STATUS: { 1239 int mode; 1240 1241 if (SB_EOF()) 1242 break; 1243 mode = SB_GET(); 1244 switch (mode) { 1245 case TELQUAL_SEND: 1246 if (my_state_is_will(TELOPT_STATUS)) 1247 send_status(); 1248 break; 1249 1250 case TELQUAL_IS: 1251 break; 1252 1253 default: 1254 break; 1255 } 1256 break; 1257 } /* end of case TELOPT_STATUS */ 1258 1259 case TELOPT_XDISPLOC: { 1260 if (SB_EOF() || SB_GET() != TELQUAL_IS) 1261 return; 1262 settimer(xdisplocsubopt); 1263 subpointer[SB_LEN()] = '\0'; 1264 (void)setenv("DISPLAY", (char *)subpointer, 1); 1265 break; 1266 } /* end of case TELOPT_XDISPLOC */ 1267 1268 case TELOPT_NEW_ENVIRON: 1269 case TELOPT_OLD_ENVIRON: { 1270 int c; 1271 char *cp, *varp, *valp; 1272 1273 if (SB_EOF()) 1274 return; 1275 c = SB_GET(); 1276 if (c == TELQUAL_IS) { 1277 if (subchar == TELOPT_OLD_ENVIRON) 1278 settimer(oenvironsubopt); 1279 else 1280 settimer(environsubopt); 1281 } else if (c != TELQUAL_INFO) { 1282 return; 1283 } 1284 1285 if (subchar == TELOPT_NEW_ENVIRON) { 1286 while (!SB_EOF()) { 1287 c = SB_GET(); 1288 if ((c == NEW_ENV_VAR) || (c == ENV_USERVAR)) 1289 break; 1290 } 1291 } else 1292 { 1293 #ifdef ENV_HACK 1294 /* 1295 * We only want to do this if we haven't already decided 1296 * whether or not the other side has its VALUE and VAR 1297 * reversed. 1298 */ 1299 if (env_ovar < 0) { 1300 int last = -1; /* invalid value */ 1301 int empty = 0; 1302 int got_var = 0, got_value = 0, got_uservar = 0; 1303 1304 /* 1305 * The other side might have its VALUE and VAR values 1306 * reversed. To be interoperable, we need to determine 1307 * which way it is. If the first recognized character 1308 * is a VAR or VALUE, then that will tell us what 1309 * type of client it is. If the fist recognized 1310 * character is a USERVAR, then we continue scanning 1311 * the suboption looking for two consecutive 1312 * VAR or VALUE fields. We should not get two 1313 * consecutive VALUE fields, so finding two 1314 * consecutive VALUE or VAR fields will tell us 1315 * what the client is. 1316 */ 1317 SB_SAVE(); 1318 while (!SB_EOF()) { 1319 c = SB_GET(); 1320 switch(c) { 1321 case OLD_ENV_VAR: 1322 if (last < 0 || last == OLD_ENV_VAR 1323 || (empty && (last == OLD_ENV_VALUE))) 1324 goto env_ovar_ok; 1325 got_var++; 1326 last = OLD_ENV_VAR; 1327 break; 1328 case OLD_ENV_VALUE: 1329 if (last < 0 || last == OLD_ENV_VALUE 1330 || (empty && (last == OLD_ENV_VAR))) 1331 goto env_ovar_wrong; 1332 got_value++; 1333 last = OLD_ENV_VALUE; 1334 break; 1335 case ENV_USERVAR: 1336 /* count strings of USERVAR as one */ 1337 if (last != ENV_USERVAR) 1338 got_uservar++; 1339 if (empty) { 1340 if (last == OLD_ENV_VALUE) 1341 goto env_ovar_ok; 1342 if (last == OLD_ENV_VAR) 1343 goto env_ovar_wrong; 1344 } 1345 last = ENV_USERVAR; 1346 break; 1347 case ENV_ESC: 1348 if (!SB_EOF()) 1349 c = SB_GET(); 1350 /* FALL THROUGH */ 1351 default: 1352 empty = 0; 1353 continue; 1354 } 1355 empty = 1; 1356 } 1357 if (empty) { 1358 if (last == OLD_ENV_VALUE) 1359 goto env_ovar_ok; 1360 if (last == OLD_ENV_VAR) 1361 goto env_ovar_wrong; 1362 } 1363 /* 1364 * Ok, the first thing was a USERVAR, and there 1365 * are not two consecutive VAR or VALUE commands, 1366 * and none of the VAR or VALUE commands are empty. 1367 * If the client has sent us a well-formed option, 1368 * then the number of VALUEs received should always 1369 * be less than or equal to the number of VARs and 1370 * USERVARs received. 1371 * 1372 * If we got exactly as many VALUEs as VARs and 1373 * USERVARs, the client has the same definitions. 1374 * 1375 * If we got exactly as many VARs as VALUEs and 1376 * USERVARS, the client has reversed definitions. 1377 */ 1378 if (got_uservar + got_var == got_value) { 1379 env_ovar_ok: 1380 env_ovar = OLD_ENV_VAR; 1381 env_ovalue = OLD_ENV_VALUE; 1382 } else if (got_uservar + got_value == got_var) { 1383 env_ovar_wrong: 1384 env_ovar = OLD_ENV_VALUE; 1385 env_ovalue = OLD_ENV_VAR; 1386 DIAG(TD_OPTIONS, {output_data( 1387 "ENVIRON VALUE and VAR are reversed!\r\n");}); 1388 1389 } 1390 } 1391 SB_RESTORE(); 1392 #endif 1393 1394 while (!SB_EOF()) { 1395 c = SB_GET(); 1396 if ((c == env_ovar) || (c == ENV_USERVAR)) 1397 break; 1398 } 1399 } 1400 1401 if (SB_EOF()) 1402 return; 1403 1404 cp = varp = (char *)subpointer; 1405 valp = 0; 1406 1407 while (!SB_EOF()) { 1408 c = SB_GET(); 1409 if (subchar == TELOPT_OLD_ENVIRON) { 1410 if (c == env_ovar) 1411 c = NEW_ENV_VAR; 1412 else if (c == env_ovalue) 1413 c = NEW_ENV_VALUE; 1414 } 1415 switch (c) { 1416 1417 case NEW_ENV_VALUE: 1418 *cp = '\0'; 1419 cp = valp = (char *)subpointer; 1420 break; 1421 1422 case NEW_ENV_VAR: 1423 case ENV_USERVAR: 1424 *cp = '\0'; 1425 if (envvarok(varp)) { 1426 if (valp) 1427 (void)setenv(varp, valp, 1); 1428 else 1429 unsetenv(varp); 1430 } 1431 cp = varp = (char *)subpointer; 1432 valp = 0; 1433 break; 1434 1435 case ENV_ESC: 1436 if (SB_EOF()) 1437 break; 1438 c = SB_GET(); 1439 /* FALL THROUGH */ 1440 default: 1441 *cp++ = c; 1442 break; 1443 } 1444 } 1445 *cp = '\0'; 1446 if (envvarok(varp)) { 1447 if (valp) 1448 (void)setenv(varp, valp, 1); 1449 else 1450 unsetenv(varp); 1451 } 1452 break; 1453 } /* end of case TELOPT_NEW_ENVIRON */ 1454 #ifdef AUTHENTICATION 1455 case TELOPT_AUTHENTICATION: 1456 if (SB_EOF()) 1457 break; 1458 switch(SB_GET()) { 1459 case TELQUAL_SEND: 1460 case TELQUAL_REPLY: 1461 /* 1462 * These are sent by us and cannot be sent by 1463 * the client. 1464 */ 1465 break; 1466 case TELQUAL_IS: 1467 auth_is(subpointer, SB_LEN()); 1468 break; 1469 case TELQUAL_NAME: 1470 auth_name(subpointer, SB_LEN()); 1471 break; 1472 } 1473 break; 1474 #endif 1475 #ifdef ENCRYPTION 1476 case TELOPT_ENCRYPT: 1477 if (SB_EOF()) 1478 break; 1479 switch(SB_GET()) { 1480 case ENCRYPT_SUPPORT: 1481 encrypt_support(subpointer, SB_LEN()); 1482 break; 1483 case ENCRYPT_IS: 1484 encrypt_is(subpointer, SB_LEN()); 1485 break; 1486 case ENCRYPT_REPLY: 1487 encrypt_reply(subpointer, SB_LEN()); 1488 break; 1489 case ENCRYPT_START: 1490 encrypt_start(subpointer, SB_LEN()); 1491 break; 1492 case ENCRYPT_END: 1493 encrypt_end(); 1494 break; 1495 case ENCRYPT_REQSTART: 1496 encrypt_request_start(subpointer, SB_LEN()); 1497 break; 1498 case ENCRYPT_REQEND: 1499 /* 1500 * We can always send an REQEND so that we cannot 1501 * get stuck encrypting. We should only get this 1502 * if we have been able to get in the correct mode 1503 * anyhow. 1504 */ 1505 encrypt_request_end(); 1506 break; 1507 case ENCRYPT_ENC_KEYID: 1508 encrypt_enc_keyid(subpointer, SB_LEN()); 1509 break; 1510 case ENCRYPT_DEC_KEYID: 1511 encrypt_dec_keyid(subpointer, SB_LEN()); 1512 break; 1513 default: 1514 break; 1515 } 1516 break; 1517 #endif /* ENCRYPTION */ 1518 1519 default: 1520 break; 1521 } /* end of switch */ 1522 1523 } /* end of suboption */ 1524 1525 #ifdef LINEMODE 1526 void 1527 doclientstat(void) 1528 { 1529 clientstat(TELOPT_LINEMODE, WILL, 0); 1530 } 1531 #endif /* LINEMODE */ 1532 1533 void 1534 send_status(void) 1535 { 1536 #define ADD(c) \ 1537 do { \ 1538 if (ep > ncp) \ 1539 *ncp++ = c; \ 1540 else \ 1541 goto trunc; \ 1542 } while (0) 1543 #define ADD_DATA(c) \ 1544 do { \ 1545 ADD(c); if (c == SE || c == IAC) ADD(c); \ 1546 } while (0) 1547 1548 unsigned char statusbuf[256]; 1549 unsigned char *ep; 1550 unsigned char *ncp; 1551 unsigned char i; 1552 1553 ncp = statusbuf; 1554 ep = statusbuf + sizeof(statusbuf); 1555 1556 netflush(); /* get rid of anything waiting to go out */ 1557 1558 ADD(IAC); 1559 ADD(SB); 1560 ADD(TELOPT_STATUS); 1561 ADD(TELQUAL_IS); 1562 1563 /* 1564 * We check the want_state rather than the current state, 1565 * because if we received a DO/WILL for an option that we 1566 * don't support, and the other side didn't send a DONT/WONT 1567 * in response to our WONT/DONT, then the "state" will be 1568 * WILL/DO, and the "want_state" will be WONT/DONT. We 1569 * need to go by the latter. 1570 */ 1571 for (i = 0; i < (unsigned char)NTELOPTS; i++) { 1572 if (my_want_state_is_will(i)) { 1573 ADD(WILL); 1574 ADD_DATA(i); 1575 } 1576 if (his_want_state_is_will(i)) { 1577 ADD(DO); 1578 ADD_DATA(i); 1579 } 1580 } 1581 1582 if (his_want_state_is_will(TELOPT_LFLOW)) { 1583 ADD(SB); 1584 ADD(TELOPT_LFLOW); 1585 if (flowmode) { 1586 ADD(LFLOW_ON); 1587 } else { 1588 ADD(LFLOW_OFF); 1589 } 1590 ADD(SE); 1591 1592 if (restartany >= 0) { 1593 ADD(SB); 1594 ADD(TELOPT_LFLOW); 1595 if (restartany) { 1596 ADD(LFLOW_RESTART_ANY); 1597 } else { 1598 ADD(LFLOW_RESTART_XON); 1599 } 1600 ADD(SE); 1601 } 1602 } 1603 1604 #ifdef LINEMODE 1605 if (his_want_state_is_will(TELOPT_LINEMODE)) { 1606 unsigned char *cp, *cpe; 1607 int len; 1608 1609 ADD(SB); 1610 ADD(TELOPT_LINEMODE); 1611 ADD(LM_MODE); 1612 ADD_DATA(editmode); 1613 ADD(SE); 1614 1615 ADD(SB); 1616 ADD(TELOPT_LINEMODE); 1617 ADD(LM_SLC); 1618 start_slc(0); 1619 send_slc(); 1620 len = end_slc(&cp); 1621 for (cpe = cp + len; cp < cpe; cp++) 1622 ADD_DATA(*cp); 1623 ADD(SE); 1624 } 1625 #endif /* LINEMODE */ 1626 1627 ADD(IAC); 1628 ADD(SE); 1629 1630 writenet(statusbuf, ncp - statusbuf); 1631 netflush(); /* Send it on its way */ 1632 1633 DIAG(TD_OPTIONS, 1634 {printsub('>', statusbuf, ncp - statusbuf); netflush();}); 1635 return; 1636 1637 trunc: 1638 /* XXX bark? */ 1639 return; 1640 #undef ADD 1641 #undef ADD_DATA 1642 } 1643 1644 int 1645 output_data(const char *format, ...) 1646 { 1647 va_list args; 1648 size_t remaining, ret; 1649 1650 va_start(args, format); 1651 remaining = BUFSIZ - (nfrontp - netobuf); 1652 /* try a netflush() if the room is too low */ 1653 if (strlen(format) > remaining || BUFSIZ / 4 > remaining) { 1654 netflush(); 1655 remaining = BUFSIZ - (nfrontp - netobuf); 1656 } 1657 ret = vsnprintf(nfrontp, remaining, format, args); 1658 nfrontp += ((ret < remaining - 1) ? ret : remaining - 1); 1659 va_end(args); 1660 return ret; 1661 } 1662 1663 int 1664 output_datalen(const char *buf, size_t l) 1665 { 1666 size_t remaining; 1667 1668 remaining = BUFSIZ - (nfrontp - netobuf); 1669 if (remaining < l) { 1670 netflush(); 1671 remaining = BUFSIZ - (nfrontp - netobuf); 1672 } 1673 if (remaining < l) 1674 return -1; 1675 memmove(nfrontp, buf, l); 1676 nfrontp += l; 1677 return (int)l; 1678 } 1679