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