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