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