1 /* 2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * Copyright (c) 1988, 1990, 1993 8 * The Regents of the University of California. All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 */ 38 39 #ifndef lint 40 static char sccsid[] = "@(#)telnet.c 8.1 (Berkeley) 6/6/93"; 41 #endif /* not lint */ 42 43 #include <netdb.h> 44 #include <sys/types.h> 45 46 #include <curses.h> 47 #include <signal.h> 48 /* 49 * By the way, we need to include curses.h before telnet.h since, 50 * among other things, telnet.h #defines 'DO', which is a variable 51 * declared in curses.h. 52 */ 53 54 #include <arpa/telnet.h> 55 56 #include <ctype.h> 57 58 #include "ring.h" 59 60 #include "defines.h" 61 #include "externs.h" 62 #include "types.h" 63 #include "general.h" 64 65 #include "auth.h" 66 #include "encrypt.h" 67 68 #define strip(x) ((x)&0x7f) 69 70 /* Buffer for sub-options */ 71 static unsigned char subbuffer[SUBBUFSIZE]; 72 static unsigned char *subpointer; 73 static unsigned char *subend; 74 75 #define SB_CLEAR() subpointer = subbuffer; 76 #define SB_TERM() { subend = subpointer; SB_CLEAR(); } 77 #define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof (subbuffer))) { \ 78 *subpointer++ = (c); \ 79 } 80 81 #define SB_GET() ((*subpointer++)&0xff) 82 #define SB_PEEK() ((*subpointer)&0xff) 83 #define SB_EOF() (subpointer >= subend) 84 #define SB_LEN() (subend - subpointer) 85 86 char options[SUBBUFSIZE]; /* The combined options */ 87 char do_dont_resp[SUBBUFSIZE]; 88 char will_wont_resp[SUBBUFSIZE]; 89 90 int eight = 0; 91 int autologin = 0; /* Autologin anyone? */ 92 int skiprc = 0; 93 int connected; 94 int showoptions; 95 static int ISend; /* trying to send network data in */ 96 int debug = 0; 97 int crmod; 98 int netdata; /* Print out network data flow */ 99 int crlf; /* Should '\r' be mapped to <CR><LF> (or <CR><NUL>)? */ 100 int telnetport; 101 int SYNCHing; /* we are in TELNET SYNCH mode */ 102 int flushout; /* flush output */ 103 int autoflush = 0; /* flush output when interrupting? */ 104 int autosynch; /* send interrupt characters with SYNCH? */ 105 int localflow; /* we handle flow control locally */ 106 int restartany; /* if flow control enabled, restart on any character */ 107 int localchars; /* we recognize interrupt/quit */ 108 int donelclchars; /* the user has set "localchars" */ 109 int donebinarytoggle; /* the user has put us in binary */ 110 int dontlecho; /* do we suppress local echoing right now? */ 111 int eof_pending = 0; /* we received a genuine EOF on input, send IAC-EOF */ 112 int globalmode; 113 114 /* spin while waiting for authentication */ 115 boolean_t scheduler_lockout_tty = B_FALSE; 116 int encrypt_flag = 0; 117 int forwardable_flag = 0; 118 int forward_flag = 0; 119 boolean_t wantencryption = B_FALSE; 120 121 char *prompt = 0; 122 123 cc_t escape; 124 cc_t rlogin; 125 boolean_t escape_valid = B_TRUE; 126 #ifdef KLUDGELINEMODE 127 cc_t echoc; 128 #endif 129 130 /* 131 * Telnet receiver states for fsm 132 */ 133 #define TS_DATA 0 134 #define TS_IAC 1 135 #define TS_WILL 2 136 #define TS_WONT 3 137 #define TS_DO 4 138 #define TS_DONT 5 139 #define TS_CR 6 140 #define TS_SB 7 /* sub-option collection */ 141 #define TS_SE 8 /* looking for sub-option end */ 142 143 static int telrcv_state; 144 #ifdef OLD_ENVIRON 145 static unsigned char telopt_environ = TELOPT_NEW_ENVIRON; 146 #else 147 #define telopt_environ TELOPT_NEW_ENVIRON 148 #endif 149 150 jmp_buf toplevel = { 0 }; 151 jmp_buf peerdied; 152 153 static int flushline; 154 int linemode; 155 156 int reqd_linemode = 0; /* Set if either new or old line mode in */ 157 /* effect since before initial negotiations */ 158 159 #ifdef KLUDGELINEMODE 160 int kludgelinemode = 1; 161 #endif 162 163 /* 164 * The following are some clocks used to decide how to interpret 165 * the relationship between various variables. 166 */ 167 168 Clocks clocks; 169 170 #ifdef notdef 171 Modelist modelist[] = { 172 { "telnet command mode", COMMAND_LINE }, 173 { "character-at-a-time mode", 0 }, 174 { "character-at-a-time mode (local echo)", LOCAL_ECHO|LOCAL_CHARS }, 175 { "line-by-line mode (remote echo)", LINE | LOCAL_CHARS }, 176 { "line-by-line mode", LINE | LOCAL_ECHO | LOCAL_CHARS }, 177 { "line-by-line mode (local echoing suppressed)", LINE | LOCAL_CHARS }, 178 { "3270 mode", 0 }, 179 }; 180 #endif 181 182 static void willoption(int); 183 static void wontoption(int); 184 static void lm_will(unsigned char *, int); 185 static void lm_wont(unsigned char *, int); 186 static void lm_do(unsigned char *, int); 187 static void lm_dont(unsigned char *, int); 188 static void slc_init(void); 189 static void slc_import(int); 190 static void slc_export(void); 191 static void slc_start_reply(size_t); 192 static void slc_add_reply(unsigned char, unsigned char, cc_t); 193 static void slc_end_reply(void); 194 static void slc(unsigned char *, int); 195 static int slc_update(void); 196 static void env_opt(unsigned char *, int); 197 static void env_opt_start(void); 198 static void sendeof(void); 199 static int is_unique(register char *, register char **, register char **); 200 201 /* 202 * Initialize telnet environment. 203 */ 204 205 int 206 init_telnet() 207 { 208 if (env_init() == 0) 209 return (0); 210 211 SB_CLEAR(); 212 ClearArray(options); 213 214 connected = ISend = localflow = donebinarytoggle = 0; 215 restartany = -1; 216 217 SYNCHing = 0; 218 219 /* Don't change NetTrace */ 220 221 escape = CONTROL(']'); 222 rlogin = _POSIX_VDISABLE; 223 #ifdef KLUDGELINEMODE 224 echoc = CONTROL('E'); 225 #endif 226 227 flushline = 1; 228 telrcv_state = TS_DATA; 229 230 return (1); 231 } 232 233 234 #ifdef notdef 235 #include <varargs.h> 236 237 /*VARARGS*/ 238 static void 239 printring(va_alist) 240 va_dcl 241 { 242 va_list ap; 243 char buffer[100]; /* where things go */ 244 char *ptr; 245 char *format; 246 char *string; 247 Ring *ring; 248 int i; 249 250 va_start(ap); 251 252 ring = va_arg(ap, Ring *); 253 format = va_arg(ap, char *); 254 ptr = buffer; 255 256 while ((i = *format++) != 0) { 257 if (i == '%') { 258 i = *format++; 259 switch (i) { 260 case 'c': 261 *ptr++ = va_arg(ap, int); 262 break; 263 case 's': 264 string = va_arg(ap, char *); 265 ring_supply_data(ring, buffer, ptr-buffer); 266 ring_supply_data(ring, string, strlen(string)); 267 ptr = buffer; 268 break; 269 case 0: 270 ExitString("printring: trailing %%.\n", 271 EXIT_FAILURE); 272 /*NOTREACHED*/ 273 default: 274 ExitString("printring: unknown format " 275 "character.\n", EXIT_FAILURE); 276 /*NOTREACHED*/ 277 } 278 } else { 279 *ptr++ = i; 280 } 281 } 282 ring_supply_data(ring, buffer, ptr-buffer); 283 } 284 #endif 285 286 /* 287 * These routines are in charge of sending option negotiations 288 * to the other side. 289 * 290 * The basic idea is that we send the negotiation if either side 291 * is in disagreement as to what the current state should be. 292 */ 293 294 void 295 send_do(c, init) 296 register int c, init; 297 { 298 if (init) { 299 if (((do_dont_resp[c] == 0) && my_state_is_do(c)) || 300 my_want_state_is_do(c)) 301 return; 302 set_my_want_state_do(c); 303 do_dont_resp[c]++; 304 } 305 NET2ADD(IAC, DO); 306 NETADD(c); 307 printoption("SENT", DO, c); 308 } 309 310 void 311 send_dont(c, init) 312 register int c, init; 313 { 314 if (init) { 315 if (((do_dont_resp[c] == 0) && my_state_is_dont(c)) || 316 my_want_state_is_dont(c)) 317 return; 318 set_my_want_state_dont(c); 319 do_dont_resp[c]++; 320 } 321 NET2ADD(IAC, DONT); 322 NETADD(c); 323 printoption("SENT", DONT, c); 324 } 325 326 void 327 send_will(c, init) 328 register int c, init; 329 { 330 if (init) { 331 if (((will_wont_resp[c] == 0) && my_state_is_will(c)) || 332 my_want_state_is_will(c)) 333 return; 334 set_my_want_state_will(c); 335 will_wont_resp[c]++; 336 } 337 NET2ADD(IAC, WILL); 338 NETADD(c); 339 printoption("SENT", WILL, c); 340 } 341 342 void 343 send_wont(c, init) 344 register int c, init; 345 { 346 if (init) { 347 if (((will_wont_resp[c] == 0) && my_state_is_wont(c)) || 348 my_want_state_is_wont(c)) 349 return; 350 set_my_want_state_wont(c); 351 will_wont_resp[c]++; 352 } 353 NET2ADD(IAC, WONT); 354 NETADD(c); 355 printoption("SENT", WONT, c); 356 } 357 358 359 static void 360 willoption(option) 361 int option; 362 { 363 int new_state_ok = 0; 364 365 if (do_dont_resp[option]) { 366 --do_dont_resp[option]; 367 if (do_dont_resp[option] && my_state_is_do(option)) 368 --do_dont_resp[option]; 369 } 370 371 if ((do_dont_resp[option] == 0) && my_want_state_is_dont(option)) { 372 373 switch (option) { 374 375 case TELOPT_ECHO: 376 case TELOPT_SGA: 377 if (reqd_linemode && my_state_is_dont(option)) { 378 break; 379 } 380 /* FALLTHROUGH */ 381 case TELOPT_BINARY: 382 settimer(modenegotiated); 383 /* FALLTHROUGH */ 384 case TELOPT_STATUS: 385 case TELOPT_AUTHENTICATION: 386 /* FALLTHROUGH */ 387 case TELOPT_ENCRYPT: 388 new_state_ok = 1; 389 break; 390 391 case TELOPT_TM: 392 if (flushout) 393 flushout = 0; 394 /* 395 * Special case for TM. If we get back a WILL, 396 * pretend we got back a WONT. 397 */ 398 set_my_want_state_dont(option); 399 set_my_state_dont(option); 400 return; /* Never reply to TM will's/wont's */ 401 402 case TELOPT_LINEMODE: 403 default: 404 break; 405 } 406 407 if (new_state_ok) { 408 set_my_want_state_do(option); 409 send_do(option, 0); 410 setconnmode(0); /* possibly set new tty mode */ 411 } else { 412 do_dont_resp[option]++; 413 send_dont(option, 0); 414 } 415 } 416 set_my_state_do(option); 417 if (option == TELOPT_ENCRYPT) 418 encrypt_send_support(); 419 } 420 421 static void 422 wontoption(option) 423 int option; 424 { 425 if (do_dont_resp[option]) { 426 --do_dont_resp[option]; 427 if (do_dont_resp[option] && my_state_is_dont(option)) 428 --do_dont_resp[option]; 429 } 430 431 if ((do_dont_resp[option] == 0) && my_want_state_is_do(option)) { 432 433 switch (option) { 434 435 #ifdef KLUDGELINEMODE 436 case TELOPT_SGA: 437 if (!kludgelinemode) 438 break; 439 /* FALLTHROUGH */ 440 #endif 441 case TELOPT_ECHO: 442 settimer(modenegotiated); 443 break; 444 445 case TELOPT_TM: 446 if (flushout) 447 flushout = 0; 448 set_my_want_state_dont(option); 449 set_my_state_dont(option); 450 return; /* Never reply to TM will's/wont's */ 451 452 default: 453 break; 454 } 455 set_my_want_state_dont(option); 456 if (my_state_is_do(option)) 457 send_dont(option, 0); 458 setconnmode(0); /* Set new tty mode */ 459 } else if (option == TELOPT_TM) { 460 /* 461 * Special case for TM. 462 */ 463 if (flushout) 464 flushout = 0; 465 set_my_want_state_dont(option); 466 } 467 set_my_state_dont(option); 468 } 469 470 static void 471 dooption(option) 472 int option; 473 { 474 int new_state_ok = 0; 475 476 if (will_wont_resp[option]) { 477 --will_wont_resp[option]; 478 if (will_wont_resp[option] && my_state_is_will(option)) 479 --will_wont_resp[option]; 480 } 481 482 if (will_wont_resp[option] == 0) { 483 if (my_want_state_is_wont(option)) { 484 485 switch (option) { 486 487 case TELOPT_TM: 488 /* 489 * Special case for TM. We send a WILL, 490 * but pretend we sent WONT. 491 */ 492 send_will(option, 0); 493 set_my_want_state_wont(TELOPT_TM); 494 set_my_state_wont(TELOPT_TM); 495 return; 496 497 case TELOPT_BINARY: /* binary mode */ 498 case TELOPT_NAWS: /* window size */ 499 case TELOPT_TSPEED: /* terminal speed */ 500 case TELOPT_LFLOW: /* local flow control */ 501 case TELOPT_TTYPE: /* terminal type option */ 502 case TELOPT_SGA: /* no big deal */ 503 case TELOPT_ENCRYPT: /* encryption variable option */ 504 new_state_ok = 1; 505 break; 506 507 case TELOPT_NEW_ENVIRON: 508 /* New environment variable option */ 509 #ifdef OLD_ENVIRON 510 if (my_state_is_will(TELOPT_OLD_ENVIRON)) 511 /* turn off the old */ 512 send_wont(TELOPT_OLD_ENVIRON, 1); 513 goto env_common; 514 case TELOPT_OLD_ENVIRON: 515 /* Old environment variable option */ 516 if (my_state_is_will(TELOPT_NEW_ENVIRON)) 517 /* Don't enable if new one is in use! */ 518 break; 519 env_common: 520 telopt_environ = option; 521 #endif 522 new_state_ok = 1; 523 break; 524 525 case TELOPT_AUTHENTICATION: 526 if (autologin) 527 new_state_ok = 1; 528 break; 529 530 case TELOPT_XDISPLOC: /* X Display location */ 531 if (env_getvalue((unsigned char *)"DISPLAY")) 532 new_state_ok = 1; 533 break; 534 535 case TELOPT_LINEMODE: 536 #ifdef KLUDGELINEMODE 537 kludgelinemode = 0; 538 send_do(TELOPT_SGA, 1); 539 #endif 540 set_my_want_state_will(TELOPT_LINEMODE); 541 send_will(option, 0); 542 set_my_state_will(TELOPT_LINEMODE); 543 slc_init(); 544 return; 545 546 case TELOPT_ECHO: /* We're never going to echo... */ 547 default: 548 break; 549 } 550 551 if (new_state_ok) { 552 set_my_want_state_will(option); 553 send_will(option, 0); 554 setconnmode(0); /* Set new tty mode */ 555 } else { 556 will_wont_resp[option]++; 557 send_wont(option, 0); 558 } 559 } else { 560 /* 561 * Handle options that need more things done after the 562 * other side has acknowledged the option. 563 */ 564 switch (option) { 565 case TELOPT_LINEMODE: 566 #ifdef KLUDGELINEMODE 567 kludgelinemode = 0; 568 send_do(TELOPT_SGA, 1); 569 #endif 570 set_my_state_will(option); 571 slc_init(); 572 send_do(TELOPT_SGA, 0); 573 return; 574 } 575 } 576 } 577 set_my_state_will(option); 578 } 579 580 static void 581 dontoption(option) 582 int option; 583 { 584 585 if (will_wont_resp[option]) { 586 --will_wont_resp[option]; 587 if (will_wont_resp[option] && my_state_is_wont(option)) 588 --will_wont_resp[option]; 589 } 590 591 if ((will_wont_resp[option] == 0) && my_want_state_is_will(option)) { 592 switch (option) { 593 case TELOPT_LINEMODE: 594 linemode = 0; /* put us back to the default state */ 595 break; 596 #ifdef OLD_ENVIRON 597 case TELOPT_NEW_ENVIRON: 598 /* 599 * The new environ option wasn't recognized, try 600 * the old one. 601 */ 602 send_will(TELOPT_OLD_ENVIRON, 1); 603 telopt_environ = TELOPT_OLD_ENVIRON; 604 break; 605 #endif 606 } 607 /* we always accept a DONT */ 608 set_my_want_state_wont(option); 609 if (my_state_is_will(option)) 610 send_wont(option, 0); 611 setconnmode(0); /* Set new tty mode */ 612 } 613 set_my_state_wont(option); 614 } 615 616 /* 617 * Given a buffer returned by tgetent(), this routine will turn 618 * the pipe seperated list of names in the buffer into an array 619 * of pointers to null terminated names. We toss out any bad, 620 * duplicate, or verbose names (names with spaces). 621 */ 622 623 static char *name_unknown = "UNKNOWN"; 624 static char *unknown[] = { 0, 0 }; 625 626 static char ** 627 mklist(buf, name) 628 char *buf, *name; 629 { 630 register int n; 631 register char c, *cp, **argvp, *cp2, **argv, **avt; 632 633 if (name) { 634 if (strlen(name) > 40u) { 635 name = 0; 636 unknown[0] = name_unknown; 637 } else { 638 unknown[0] = name; 639 upcase(name); 640 } 641 } else 642 unknown[0] = name_unknown; 643 /* 644 * Count up the number of names. 645 */ 646 for (n = 1, cp = buf; *cp && *cp != ':'; cp++) { 647 if (*cp == '|') 648 n++; 649 } 650 /* 651 * Allocate an array to put the name pointers into 652 */ 653 argv = malloc((n+3)*sizeof (char *)); 654 if (argv == 0) 655 return (unknown); 656 657 /* 658 * Fill up the array of pointers to names. 659 */ 660 *argv = 0; 661 argvp = argv+1; 662 n = 0; 663 for (cp = cp2 = buf; (c = *cp) != '\0'; cp++) { 664 if (c == '|' || c == ':') { 665 *cp++ = '\0'; 666 /* 667 * Skip entries that have spaces or are over 40 668 * characters long. If this is our environment 669 * name, then put it up front. Otherwise, as 670 * long as this is not a duplicate name (case 671 * insensitive) add it to the list. 672 */ 673 if (n || (cp - cp2 > 41)) 674 /* EMPTY */; 675 else if (name && (strncasecmp(name, cp2, cp-cp2) == 0)) 676 *argv = cp2; 677 else if (is_unique(cp2, argv+1, argvp)) 678 *argvp++ = cp2; 679 if (c == ':') 680 break; 681 /* 682 * Skip multiple delimiters. Reset cp2 to 683 * the beginning of the next name. Reset n, 684 * the flag for names with spaces. 685 */ 686 while ((c = *cp) == '|') 687 cp++; 688 cp2 = cp; 689 n = 0; 690 } 691 /* 692 * Skip entries with spaces or non-ascii values. 693 * Convert lower case letters to upper case. 694 */ 695 if ((c == ' ') || !isascii(c)) 696 n = 1; 697 else if (islower(c)) 698 *cp = toupper(c); 699 } 700 701 /* 702 * Check for an old V6 2 character name. If the second 703 * name points to the beginning of the buffer, and is 704 * only 2 characters long, move it to the end of the array. 705 */ 706 if ((argv[1] == buf) && (strlen(argv[1]) == 2)) { 707 --argvp; 708 for (avt = &argv[1]; avt < argvp; avt++) 709 *avt = *(avt+1); 710 *argvp++ = buf; 711 } 712 713 /* 714 * Duplicate last name, for TTYPE option, and null 715 * terminate the array. If we didn't find a match on 716 * our terminal name, put that name at the beginning. 717 */ 718 cp = *(argvp-1); 719 *argvp++ = cp; 720 *argvp = 0; 721 722 if (*argv == 0) { 723 if (name) 724 *argv = name; 725 else { 726 --argvp; 727 for (avt = argv; avt < argvp; avt++) 728 *avt = *(avt+1); 729 } 730 } 731 if (*argv) 732 return (argv); 733 else 734 return (unknown); 735 } 736 737 static int 738 is_unique(name, as, ae) 739 register char *name, **as, **ae; 740 { 741 register char **ap; 742 register int n; 743 744 n = strlen(name) + 1; 745 for (ap = as; ap < ae; ap++) 746 if (strncasecmp(*ap, name, n) == 0) 747 return (0); 748 return (1); 749 } 750 751 #define termbuf ttytype 752 extern char ttytype[]; 753 754 int resettermname = 1; 755 756 static char * 757 gettermname(void) 758 { 759 char *tname; 760 static char **tnamep = 0; 761 static char **next; 762 int err; 763 764 if (resettermname) { 765 resettermname = 0; 766 if (tnamep && tnamep != unknown) 767 free(tnamep); 768 tname = (char *)env_getvalue((unsigned char *)"TERM"); 769 if ((tname != NULL) && (setupterm(tname, 1, &err) == 0)) { 770 tnamep = mklist(termbuf, tname); 771 } else { 772 if (tname && (strlen(tname) <= 40u)) { 773 unknown[0] = tname; 774 upcase(tname); 775 } else 776 unknown[0] = name_unknown; 777 tnamep = unknown; 778 } 779 next = tnamep; 780 } 781 if (*next == 0) 782 next = tnamep; 783 return (*next++); 784 } 785 /* 786 * suboption() 787 * 788 * Look at the sub-option buffer, and try to be helpful to the other 789 * side. 790 * 791 * Currently we recognize: 792 * 793 * Terminal type, send request. 794 * Terminal speed (send request). 795 * Local flow control (is request). 796 * Linemode 797 */ 798 799 static void 800 suboption() 801 { 802 unsigned char subchar; 803 804 printsub('<', subbuffer, SB_LEN()+2); 805 switch (subchar = SB_GET()) { 806 case TELOPT_TTYPE: 807 if (my_want_state_is_wont(TELOPT_TTYPE)) 808 return; 809 if (SB_EOF() || SB_GET() != TELQUAL_SEND) { 810 return; 811 } else { 812 char *name; 813 unsigned char temp[50]; 814 int len, bytes; 815 816 name = gettermname(); 817 len = strlen(name) + 4 + 2; 818 bytes = snprintf((char *)temp, sizeof (temp), 819 "%c%c%c%c%s%c%c", IAC, SB, 820 TELOPT_TTYPE, TELQUAL_IS, name, IAC, SE); 821 if ((len < NETROOM()) && (bytes < sizeof (temp))) { 822 ring_supply_data(&netoring, temp, len); 823 printsub('>', &temp[2], len-2); 824 } else { 825 ExitString("No room in buffer for " 826 "terminal type.\n", EXIT_FAILURE); 827 /*NOTREACHED*/ 828 } 829 } 830 break; 831 case TELOPT_TSPEED: 832 if (my_want_state_is_wont(TELOPT_TSPEED)) 833 return; 834 if (SB_EOF()) 835 return; 836 if (SB_GET() == TELQUAL_SEND) { 837 int ospeed, ispeed; 838 unsigned char temp[50]; 839 int len, bytes; 840 841 TerminalSpeeds(&ispeed, &ospeed); 842 843 bytes = snprintf((char *)temp, sizeof (temp), 844 "%c%c%c%c%d,%d%c%c", IAC, SB, 845 TELOPT_TSPEED, TELQUAL_IS, ospeed, ispeed, IAC, SE); 846 len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */ 847 848 if ((len < NETROOM()) && (bytes < sizeof (temp))) { 849 ring_supply_data(&netoring, temp, len); 850 printsub('>', temp+2, len - 2); 851 } 852 else 853 (void) printf( 854 "telnet: not enough room in buffer " 855 "for terminal speed option reply\n"); 856 } 857 break; 858 case TELOPT_LFLOW: 859 if (my_want_state_is_wont(TELOPT_LFLOW)) 860 return; 861 if (SB_EOF()) 862 return; 863 switch (SB_GET()) { 864 case LFLOW_RESTART_ANY: 865 restartany = 1; 866 break; 867 case LFLOW_RESTART_XON: 868 restartany = 0; 869 break; 870 case LFLOW_ON: 871 localflow = 1; 872 break; 873 case LFLOW_OFF: 874 localflow = 0; 875 break; 876 default: 877 return; 878 } 879 setcommandmode(); 880 setconnmode(0); 881 break; 882 883 case TELOPT_LINEMODE: 884 if (my_want_state_is_wont(TELOPT_LINEMODE)) 885 return; 886 if (SB_EOF()) 887 return; 888 switch (SB_GET()) { 889 case WILL: 890 lm_will(subpointer, SB_LEN()); 891 break; 892 case WONT: 893 lm_wont(subpointer, SB_LEN()); 894 break; 895 case DO: 896 lm_do(subpointer, SB_LEN()); 897 break; 898 case DONT: 899 lm_dont(subpointer, SB_LEN()); 900 break; 901 case LM_SLC: 902 slc(subpointer, SB_LEN()); 903 break; 904 case LM_MODE: 905 lm_mode(subpointer, SB_LEN(), 0); 906 break; 907 default: 908 break; 909 } 910 break; 911 912 #ifdef OLD_ENVIRON 913 case TELOPT_OLD_ENVIRON: 914 #endif 915 case TELOPT_NEW_ENVIRON: 916 if (SB_EOF()) 917 return; 918 switch (SB_PEEK()) { 919 case TELQUAL_IS: 920 case TELQUAL_INFO: 921 if (my_want_state_is_dont(subchar)) 922 return; 923 break; 924 case TELQUAL_SEND: 925 if (my_want_state_is_wont(subchar)) { 926 return; 927 } 928 break; 929 default: 930 return; 931 } 932 env_opt(subpointer, SB_LEN()); 933 break; 934 935 case TELOPT_XDISPLOC: 936 if (my_want_state_is_wont(TELOPT_XDISPLOC)) 937 return; 938 if (SB_EOF()) 939 return; 940 if (SB_GET() == TELQUAL_SEND) { 941 unsigned char temp[50], *dp; 942 int len, bytes; 943 944 if ((dp = env_getvalue((unsigned char *)"DISPLAY")) == 945 NULL) { 946 /* 947 * Something happened, we no longer have a 948 * DISPLAY variable. So, turn off the option. 949 */ 950 send_wont(TELOPT_XDISPLOC, 1); 951 break; 952 } 953 bytes = snprintf((char *)temp, sizeof (temp), 954 "%c%c%c%c%s%c%c", IAC, SB, 955 TELOPT_XDISPLOC, TELQUAL_IS, dp, IAC, SE); 956 len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */ 957 958 if ((len < NETROOM()) && (bytes < sizeof (temp))) { 959 ring_supply_data(&netoring, temp, len); 960 printsub('>', temp+2, len - 2); 961 } 962 else 963 (void) printf( 964 "telnet: not enough room in buffer" 965 " for display location option reply\n"); 966 } 967 break; 968 969 case TELOPT_AUTHENTICATION: { 970 if (!autologin) 971 break; 972 if (SB_EOF()) 973 return; 974 switch (SB_GET()) { 975 case TELQUAL_SEND: 976 if (my_want_state_is_wont(TELOPT_AUTHENTICATION)) 977 return; 978 auth_send(subpointer, SB_LEN()); 979 break; 980 case TELQUAL_REPLY: 981 if (my_want_state_is_wont(TELOPT_AUTHENTICATION)) 982 return; 983 auth_reply(subpointer, SB_LEN()); 984 break; 985 } 986 } 987 break; 988 989 case TELOPT_ENCRYPT: 990 if (SB_EOF()) 991 return; 992 switch (SB_GET()) { 993 case ENCRYPT_START: 994 if (my_want_state_is_dont(TELOPT_ENCRYPT)) 995 return; 996 encrypt_start(subpointer, SB_LEN()); 997 break; 998 case ENCRYPT_END: 999 if (my_want_state_is_dont(TELOPT_ENCRYPT)) 1000 return; 1001 encrypt_end(); 1002 break; 1003 case ENCRYPT_SUPPORT: 1004 if (my_want_state_is_wont(TELOPT_ENCRYPT)) 1005 return; 1006 encrypt_support(subpointer, SB_LEN()); 1007 break; 1008 case ENCRYPT_REQSTART: 1009 if (my_want_state_is_wont(TELOPT_ENCRYPT)) 1010 return; 1011 encrypt_request_start(subpointer, SB_LEN()); 1012 break; 1013 case ENCRYPT_REQEND: 1014 if (my_want_state_is_wont(TELOPT_ENCRYPT)) 1015 return; 1016 /* 1017 * We can always send an REQEND so that we cannot 1018 * get stuck encrypting. We should only get this 1019 * if we have been able to get in the correct mode 1020 * anyhow. 1021 */ 1022 encrypt_request_end(); 1023 break; 1024 case ENCRYPT_IS: 1025 if (my_want_state_is_dont(TELOPT_ENCRYPT)) 1026 return; 1027 encrypt_is(subpointer, SB_LEN()); 1028 break; 1029 case ENCRYPT_REPLY: 1030 if (my_want_state_is_wont(TELOPT_ENCRYPT)) 1031 return; 1032 encrypt_reply(subpointer, SB_LEN()); 1033 break; 1034 case ENCRYPT_ENC_KEYID: 1035 if (my_want_state_is_dont(TELOPT_ENCRYPT)) 1036 return; 1037 encrypt_enc_keyid(subpointer, SB_LEN()); 1038 break; 1039 case ENCRYPT_DEC_KEYID: 1040 if (my_want_state_is_wont(TELOPT_ENCRYPT)) 1041 return; 1042 encrypt_dec_keyid(subpointer, SB_LEN()); 1043 break; 1044 default: 1045 break; 1046 } 1047 break; 1048 default: 1049 break; 1050 } 1051 } 1052 1053 static unsigned char str_lm[] = { IAC, SB, TELOPT_LINEMODE, 0, 0, IAC, SE }; 1054 1055 static void 1056 lm_will(cmd, len) 1057 unsigned char *cmd; 1058 int len; 1059 { 1060 if (len < 1) { 1061 /* Should not happen... */ 1062 (void) printf( 1063 "telnet: command missing from linemode WILL request\n"); 1064 return; 1065 } 1066 switch (cmd[0]) { 1067 case LM_FORWARDMASK: /* We shouldn't ever get this... */ 1068 default: 1069 str_lm[3] = DONT; 1070 str_lm[4] = cmd[0]; 1071 if (NETROOM() > sizeof (str_lm)) { 1072 ring_supply_data(&netoring, str_lm, sizeof (str_lm)); 1073 printsub('>', &str_lm[2], sizeof (str_lm)-2); 1074 } 1075 else 1076 (void) printf("telnet: not enough room in buffer for" 1077 "reply to linemode WILL request\n"); 1078 break; 1079 } 1080 } 1081 1082 static void 1083 lm_wont(cmd, len) 1084 unsigned char *cmd; 1085 int len; 1086 { 1087 if (len < 1) { 1088 /* Should not happen... */ 1089 (void) printf( 1090 "telnet: command missing from linemode WONT request\n"); 1091 return; 1092 } 1093 switch (cmd[0]) { 1094 case LM_FORWARDMASK: /* We shouldn't ever get this... */ 1095 default: 1096 /* We are always DONT, so don't respond */ 1097 return; 1098 } 1099 } 1100 1101 static void 1102 lm_do(cmd, len) 1103 unsigned char *cmd; 1104 int len; 1105 { 1106 if (len < 1) { 1107 /* Should not happen... */ 1108 (void) printf( 1109 "telnet: command missing from linemode DO request\n"); 1110 return; 1111 } 1112 switch (cmd[0]) { 1113 case LM_FORWARDMASK: 1114 default: 1115 str_lm[3] = WONT; 1116 str_lm[4] = cmd[0]; 1117 if (NETROOM() > sizeof (str_lm)) { 1118 ring_supply_data(&netoring, str_lm, sizeof (str_lm)); 1119 printsub('>', &str_lm[2], sizeof (str_lm)-2); 1120 } 1121 else 1122 (void) printf("telnet: not enough room in buffer for" 1123 "reply to linemode DO request\n"); 1124 break; 1125 } 1126 } 1127 1128 static void 1129 lm_dont(cmd, len) 1130 unsigned char *cmd; 1131 int len; 1132 { 1133 if (len < 1) { 1134 /* Should not happen... */ 1135 (void) printf( 1136 "telnet: command missing from linemode DONT request\n"); 1137 return; 1138 } 1139 switch (cmd[0]) { 1140 case LM_FORWARDMASK: 1141 default: 1142 /* we are always WONT, so don't respond */ 1143 break; 1144 } 1145 } 1146 1147 static unsigned char str_lm_mode[] = { 1148 IAC, SB, TELOPT_LINEMODE, LM_MODE, 0, IAC, SE 1149 }; 1150 1151 void 1152 lm_mode(cmd, len, init) 1153 unsigned char *cmd; 1154 int len, init; 1155 { 1156 if (len != 1) 1157 return; 1158 if ((linemode&MODE_MASK&~MODE_ACK) == *cmd) 1159 return; 1160 linemode = *cmd&(MODE_MASK&~MODE_ACK); 1161 str_lm_mode[4] = linemode; 1162 if (!init) 1163 str_lm_mode[4] |= MODE_ACK; 1164 if (NETROOM() > sizeof (str_lm_mode)) { 1165 ring_supply_data(&netoring, str_lm_mode, sizeof (str_lm_mode)); 1166 printsub('>', &str_lm_mode[2], sizeof (str_lm_mode)-2); 1167 } 1168 else 1169 (void) printf("telnet: not enough room in buffer for" 1170 "reply to linemode request\n"); 1171 setconnmode(0); /* set changed mode */ 1172 } 1173 1174 1175 1176 /* 1177 * slc() 1178 * Handle special character suboption of LINEMODE. 1179 */ 1180 1181 static struct spc { 1182 cc_t val; 1183 cc_t *valp; 1184 char flags; /* Current flags & level */ 1185 char mylevel; /* Maximum level & flags */ 1186 } spc_data[NSLC+1]; 1187 1188 #define SLC_IMPORT 0 1189 #define SLC_EXPORT 1 1190 #define SLC_RVALUE 2 1191 static int slc_mode = SLC_EXPORT; 1192 1193 static void 1194 slc_init() 1195 { 1196 register struct spc *spcp; 1197 1198 localchars = 1; 1199 for (spcp = spc_data; spcp < &spc_data[NSLC+1]; spcp++) { 1200 spcp->val = 0; 1201 spcp->valp = 0; 1202 spcp->flags = spcp->mylevel = SLC_NOSUPPORT; 1203 } 1204 1205 #define initfunc(func, flags) { \ 1206 spcp = &spc_data[func]; \ 1207 if (spcp->valp = tcval(func)) { \ 1208 spcp->val = *spcp->valp; \ 1209 spcp->mylevel = SLC_VARIABLE|(flags);\ 1210 } else { \ 1211 spcp->val = 0; \ 1212 spcp->mylevel = SLC_DEFAULT; \ 1213 } \ 1214 } 1215 1216 initfunc(SLC_SYNCH, 0); 1217 /* No BRK */ 1218 initfunc(SLC_AO, 0); 1219 initfunc(SLC_AYT, 0); 1220 /* No EOR */ 1221 initfunc(SLC_ABORT, SLC_FLUSHIN|SLC_FLUSHOUT); 1222 initfunc(SLC_EOF, 0); 1223 initfunc(SLC_SUSP, SLC_FLUSHIN); 1224 initfunc(SLC_EC, 0); 1225 initfunc(SLC_EL, 0); 1226 initfunc(SLC_EW, 0); 1227 initfunc(SLC_RP, 0); 1228 initfunc(SLC_LNEXT, 0); 1229 initfunc(SLC_XON, 0); 1230 initfunc(SLC_XOFF, 0); 1231 initfunc(SLC_FORW1, 0); 1232 #ifdef USE_TERMIO 1233 initfunc(SLC_FORW2, 0); 1234 /* No FORW2 */ 1235 #endif 1236 1237 initfunc(SLC_IP, SLC_FLUSHIN|SLC_FLUSHOUT); 1238 #undef initfunc 1239 1240 if (slc_mode == SLC_EXPORT) 1241 slc_export(); 1242 else 1243 slc_import(1); 1244 1245 } 1246 1247 void 1248 slcstate() 1249 { 1250 (void) printf("Special characters are %s values\n", 1251 slc_mode == SLC_IMPORT ? "remote default" : 1252 slc_mode == SLC_EXPORT ? "local" : 1253 "remote"); 1254 } 1255 1256 void 1257 slc_mode_export() 1258 { 1259 slc_mode = SLC_EXPORT; 1260 if (my_state_is_will(TELOPT_LINEMODE)) 1261 slc_export(); 1262 } 1263 1264 void 1265 slc_mode_import(def) 1266 int def; 1267 { 1268 slc_mode = def ? SLC_IMPORT : SLC_RVALUE; 1269 if (my_state_is_will(TELOPT_LINEMODE)) 1270 slc_import(def); 1271 } 1272 1273 static unsigned char slc_import_val[] = { 1274 IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE 1275 }; 1276 static unsigned char slc_import_def[] = { 1277 IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE 1278 }; 1279 1280 static void 1281 slc_import(def) 1282 int def; 1283 { 1284 if (NETROOM() > sizeof (slc_import_val)) { 1285 if (def) { 1286 ring_supply_data(&netoring, slc_import_def, 1287 sizeof (slc_import_def)); 1288 printsub('>', &slc_import_def[2], 1289 sizeof (slc_import_def)-2); 1290 } else { 1291 ring_supply_data(&netoring, slc_import_val, 1292 sizeof (slc_import_val)); 1293 printsub('>', &slc_import_val[2], 1294 sizeof (slc_import_val)-2); 1295 } 1296 } 1297 else 1298 (void) printf( 1299 "telnet: not enough room in buffer for slc import" 1300 " request\n"); 1301 } 1302 1303 static uchar_t *slc_reply = NULL; 1304 static uchar_t *slc_replyp = NULL; 1305 /* 1306 * The SLC reply consists of: IAC, SB, TELOPT_LINEMODE, LM_SLC, 1307 * SLC triplets[], IAC, SE. i.e. it has a 'wrapper' of 6 control characters. 1308 */ 1309 #define SLC_WRAPPER_SIZE 6 1310 1311 static void 1312 slc_export() 1313 { 1314 register struct spc *spcp; 1315 1316 TerminalDefaultChars(); 1317 1318 slc_start_reply(NSLC * 3); /* 3 bytes needed per triplet */ 1319 for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) { 1320 if (spcp->mylevel != SLC_NOSUPPORT) { 1321 if (spcp->val == (cc_t)(_POSIX_VDISABLE)) 1322 spcp->flags = SLC_NOSUPPORT; 1323 else 1324 spcp->flags = spcp->mylevel; 1325 if (spcp->valp) 1326 spcp->val = *spcp->valp; 1327 slc_add_reply(spcp - spc_data, spcp->flags, spcp->val); 1328 } 1329 } 1330 slc_end_reply(); 1331 (void) slc_update(); 1332 setconnmode(1); /* Make sure the character values are set */ 1333 } 1334 1335 static void 1336 slc(cp, len) 1337 register unsigned char *cp; 1338 int len; 1339 { 1340 register struct spc *spcp; 1341 register int func, level; 1342 1343 slc_start_reply(len); 1344 1345 for (; len >= 3; len -= 3, cp += 3) { 1346 1347 func = cp[SLC_FUNC]; 1348 1349 if (func == 0) { 1350 /* 1351 * Client side: always ignore 0 function. 1352 */ 1353 continue; 1354 } 1355 if (func > NSLC) { 1356 if ((cp[SLC_FLAGS] & SLC_LEVELBITS) != SLC_NOSUPPORT) 1357 slc_add_reply(func, SLC_NOSUPPORT, 0); 1358 continue; 1359 } 1360 1361 spcp = &spc_data[func]; 1362 1363 level = cp[SLC_FLAGS]&(SLC_LEVELBITS|SLC_ACK); 1364 1365 if ((cp[SLC_VALUE] == (unsigned char)spcp->val) && 1366 ((level&SLC_LEVELBITS) == (spcp->flags&SLC_LEVELBITS))) { 1367 continue; 1368 } 1369 1370 if (level == (SLC_DEFAULT|SLC_ACK)) { 1371 /* 1372 * This is an error condition, the SLC_ACK 1373 * bit should never be set for the SLC_DEFAULT 1374 * level. Our best guess to recover is to 1375 * ignore the SLC_ACK bit. 1376 */ 1377 cp[SLC_FLAGS] &= ~SLC_ACK; 1378 } 1379 1380 if (level == ((spcp->flags&SLC_LEVELBITS)|SLC_ACK)) { 1381 spcp->val = (cc_t)cp[SLC_VALUE]; 1382 spcp->flags = cp[SLC_FLAGS]; /* include SLC_ACK */ 1383 continue; 1384 } 1385 1386 level &= ~SLC_ACK; 1387 1388 if (level <= (spcp->mylevel&SLC_LEVELBITS)) { 1389 spcp->flags = cp[SLC_FLAGS]|SLC_ACK; 1390 spcp->val = (cc_t)cp[SLC_VALUE]; 1391 } 1392 if (level == SLC_DEFAULT) { 1393 if ((spcp->mylevel&SLC_LEVELBITS) != SLC_DEFAULT) 1394 spcp->flags = spcp->mylevel; 1395 else 1396 spcp->flags = SLC_NOSUPPORT; 1397 } 1398 slc_add_reply(func, spcp->flags, spcp->val); 1399 } 1400 slc_end_reply(); 1401 if (slc_update()) 1402 setconnmode(1); /* set the new character values */ 1403 } 1404 1405 void 1406 slc_check() 1407 { 1408 register struct spc *spcp; 1409 1410 slc_start_reply(NSLC * 3); /* 3 bytes needed per triplet */ 1411 for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) { 1412 if (spcp->valp && spcp->val != *spcp->valp) { 1413 spcp->val = *spcp->valp; 1414 if (spcp->val == (cc_t)(_POSIX_VDISABLE)) 1415 spcp->flags = SLC_NOSUPPORT; 1416 else 1417 spcp->flags = spcp->mylevel; 1418 slc_add_reply(spcp - spc_data, spcp->flags, spcp->val); 1419 } 1420 } 1421 slc_end_reply(); 1422 setconnmode(1); 1423 } 1424 1425 static void 1426 slc_start_reply(size_t len) 1427 { 1428 /* 1429 * SLC triplets may contain escaped characters, allow for 1430 * worst case by allocating 2 bytes for every character. 1431 */ 1432 slc_reply = realloc(slc_reply, (len * 2) + SLC_WRAPPER_SIZE); 1433 if (slc_reply == NULL) { 1434 fprintf(stderr, "telnet: error allocating SLC reply memory\n"); 1435 return; 1436 } 1437 slc_replyp = slc_reply; 1438 *slc_replyp++ = IAC; 1439 *slc_replyp++ = SB; 1440 *slc_replyp++ = TELOPT_LINEMODE; 1441 *slc_replyp++ = LM_SLC; 1442 } 1443 1444 static void 1445 slc_add_reply(unsigned char func, unsigned char flags, cc_t value) 1446 { 1447 if ((*slc_replyp++ = func) == IAC) 1448 *slc_replyp++ = IAC; 1449 if ((*slc_replyp++ = flags) == IAC) 1450 *slc_replyp++ = IAC; 1451 if ((*slc_replyp++ = (unsigned char)value) == IAC) 1452 *slc_replyp++ = IAC; 1453 } 1454 1455 static void 1456 slc_end_reply() 1457 { 1458 register int len; 1459 1460 *slc_replyp++ = IAC; 1461 *slc_replyp++ = SE; 1462 len = slc_replyp - slc_reply; 1463 if (len <= SLC_WRAPPER_SIZE) 1464 return; 1465 if (NETROOM() > len) { 1466 ring_supply_data(&netoring, slc_reply, slc_replyp - slc_reply); 1467 printsub('>', &slc_reply[2], slc_replyp - slc_reply - 2); 1468 } 1469 else 1470 (void) printf("telnet: not enough room in buffer for slc end " 1471 "reply\n"); 1472 } 1473 1474 static int 1475 slc_update() 1476 { 1477 register struct spc *spcp; 1478 int need_update = 0; 1479 1480 for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) { 1481 if (!(spcp->flags&SLC_ACK)) 1482 continue; 1483 spcp->flags &= ~SLC_ACK; 1484 if (spcp->valp && (*spcp->valp != spcp->val)) { 1485 *spcp->valp = spcp->val; 1486 need_update = 1; 1487 } 1488 } 1489 return (need_update); 1490 } 1491 1492 #ifdef OLD_ENVIRON 1493 #ifdef ENV_HACK 1494 /* 1495 * Earlier version of telnet/telnetd from the BSD code had 1496 * the definitions of VALUE and VAR reversed. To ensure 1497 * maximum interoperability, we assume that the server is 1498 * an older BSD server, until proven otherwise. The newer 1499 * BSD servers should be able to handle either definition, 1500 * so it is better to use the wrong values if we don't 1501 * know what type of server it is. 1502 */ 1503 int env_auto = 1; 1504 int old_env_var = OLD_ENV_VAR; 1505 int old_env_value = OLD_ENV_VALUE; 1506 #else 1507 #define old_env_var OLD_ENV_VAR 1508 #define old_env_value OLD_ENV_VALUE 1509 #endif 1510 #endif 1511 1512 static void 1513 env_opt(buf, len) 1514 register unsigned char *buf; 1515 register int len; 1516 { 1517 register unsigned char *ep = 0, *epc = 0; 1518 register int i; 1519 1520 switch (buf[0]&0xff) { 1521 case TELQUAL_SEND: 1522 env_opt_start(); 1523 if (len == 1) { 1524 env_opt_add(NULL); 1525 } else for (i = 1; i < len; i++) { 1526 switch (buf[i]&0xff) { 1527 #ifdef OLD_ENVIRON 1528 case OLD_ENV_VAR: 1529 #ifdef ENV_HACK 1530 if (telopt_environ == TELOPT_OLD_ENVIRON && 1531 env_auto) { 1532 /* Server has the same definitions */ 1533 old_env_var = OLD_ENV_VAR; 1534 old_env_value = OLD_ENV_VALUE; 1535 } 1536 /* FALLTHROUGH */ 1537 #endif 1538 case OLD_ENV_VALUE: 1539 /* 1540 * Although OLD_ENV_VALUE is not legal, we will 1541 * still recognize it, just in case it is an 1542 * old server that has VAR & VALUE mixed up... 1543 */ 1544 /* FALLTHROUGH */ 1545 #else 1546 case NEW_ENV_VAR: 1547 #endif 1548 case ENV_USERVAR: 1549 if (ep) { 1550 *epc = 0; 1551 env_opt_add(ep); 1552 } 1553 ep = epc = &buf[i+1]; 1554 break; 1555 case ENV_ESC: 1556 i++; 1557 /*FALLTHROUGH*/ 1558 default: 1559 if (epc) 1560 *epc++ = buf[i]; 1561 break; 1562 } 1563 } 1564 if (ep) { 1565 *epc = 0; 1566 env_opt_add(ep); 1567 } 1568 env_opt_end(1); 1569 break; 1570 1571 case TELQUAL_IS: 1572 case TELQUAL_INFO: 1573 /* Ignore for now. We shouldn't get it anyway. */ 1574 break; 1575 1576 default: 1577 break; 1578 } 1579 } 1580 1581 static unsigned char *opt_reply; 1582 static unsigned char *opt_replyp; 1583 static unsigned char *opt_replyend; 1584 #define OPT_REPLY_INITIAL_SIZE 256 1585 /* 1586 * The opt reply consists of: IAC, SB, telopt_environ, TELQUAL_IS, 1587 * value, IAC, SE. i.e. it has a 'wrapper' of 6 control characters. 1588 */ 1589 #define OPT_WRAPPER_SIZE 6 1590 1591 static void 1592 env_opt_start() 1593 { 1594 opt_reply = realloc(opt_reply, OPT_REPLY_INITIAL_SIZE); 1595 if (opt_reply == NULL) { 1596 (void) printf( 1597 "telnet: error allocating environment option memory\n"); 1598 opt_reply = opt_replyp = opt_replyend = NULL; 1599 return; 1600 } 1601 opt_replyp = opt_reply; 1602 opt_replyend = opt_reply + OPT_REPLY_INITIAL_SIZE; 1603 *opt_replyp++ = IAC; 1604 *opt_replyp++ = SB; 1605 *opt_replyp++ = telopt_environ; 1606 *opt_replyp++ = TELQUAL_IS; 1607 } 1608 1609 void 1610 env_opt_start_info() 1611 { 1612 env_opt_start(); 1613 if (opt_replyp) 1614 opt_replyp[-1] = TELQUAL_INFO; 1615 } 1616 1617 void 1618 env_opt_add(ep) 1619 register unsigned char *ep; 1620 { 1621 register unsigned char *vp, c; 1622 int opt_reply_size; 1623 int opt_reply_used; 1624 1625 if (opt_reply == NULL) /* XXX */ 1626 return; /* XXX */ 1627 1628 if (ep == NULL || *ep == '\0') { 1629 /* Send user defined variables first. */ 1630 (void) env_default(1, 0); 1631 while (ep = env_default(0, 0)) 1632 env_opt_add(ep); 1633 1634 /* Now add the list of well know variables. */ 1635 (void) env_default(1, 1); 1636 while (ep = env_default(0, 1)) 1637 env_opt_add(ep); 1638 return; 1639 } 1640 vp = env_getvalue(ep); 1641 1642 /* 1643 * Calculate space required for opt_reply and allocate more if required. 1644 * Assume worst case that every character is escaped, so needs 2 bytes. 1645 */ 1646 opt_reply_used = opt_replyp - opt_reply; /* existing contents */ 1647 opt_reply_size = opt_reply_used + OPT_WRAPPER_SIZE + 1648 (2 * (strlen((char *)ep))) + 1649 (vp == NULL ? 0 : (2 * strlen((char *)vp))); 1650 1651 if (opt_reply_size > (opt_replyend - opt_reply)) { 1652 opt_reply = realloc(opt_reply, opt_reply_size); 1653 if (opt_reply == NULL) { 1654 (void) printf( 1655 "telnet: can't allocate environment option " 1656 "reply\n"); 1657 opt_reply = opt_replyp = opt_replyend = NULL; 1658 return; 1659 } 1660 opt_replyp = opt_reply + opt_reply_used; 1661 opt_replyend = opt_reply + opt_reply_size; 1662 } 1663 1664 if (opt_welldefined((char *)ep)) 1665 #ifdef OLD_ENVIRON 1666 if (telopt_environ == TELOPT_OLD_ENVIRON) 1667 *opt_replyp++ = old_env_var; 1668 else 1669 #endif 1670 *opt_replyp++ = NEW_ENV_VAR; 1671 else 1672 *opt_replyp++ = ENV_USERVAR; 1673 for (;;) { 1674 while ((c = *ep++) != '\0') { 1675 switch (c&0xff) { 1676 case IAC: 1677 *opt_replyp++ = IAC; 1678 break; 1679 case NEW_ENV_VAR: 1680 case NEW_ENV_VALUE: 1681 case ENV_ESC: 1682 case ENV_USERVAR: 1683 *opt_replyp++ = ENV_ESC; 1684 break; 1685 } 1686 *opt_replyp++ = c; 1687 } 1688 if ((ep = vp) != NULL) { 1689 #ifdef OLD_ENVIRON 1690 if (telopt_environ == TELOPT_OLD_ENVIRON) 1691 *opt_replyp++ = old_env_value; 1692 else 1693 #endif 1694 *opt_replyp++ = NEW_ENV_VALUE; 1695 vp = NULL; 1696 } else 1697 break; 1698 } 1699 } 1700 1701 int 1702 opt_welldefined(ep) 1703 char *ep; 1704 { 1705 if ((strcmp(ep, "USER") == 0) || 1706 (strcmp(ep, "DISPLAY") == 0) || 1707 (strcmp(ep, "PRINTER") == 0) || 1708 (strcmp(ep, "SYSTEMTYPE") == 0) || 1709 (strcmp(ep, "JOB") == 0) || 1710 (strcmp(ep, "ACCT") == 0)) 1711 return (1); 1712 return (0); 1713 } 1714 void 1715 env_opt_end(emptyok) 1716 register int emptyok; 1717 { 1718 register int len; 1719 1720 len = opt_replyp - opt_reply + 2; 1721 if (emptyok || len > OPT_WRAPPER_SIZE) { 1722 *opt_replyp++ = IAC; 1723 *opt_replyp++ = SE; 1724 if (NETROOM() > len) { 1725 ring_supply_data(&netoring, opt_reply, len); 1726 printsub('>', &opt_reply[2], len - 2); 1727 } 1728 else 1729 (void) printf("telnet: not enough room in buffer for " 1730 "environment option end reply\n"); 1731 } 1732 if (opt_reply) { 1733 free(opt_reply); 1734 opt_reply = opt_replyp = opt_replyend = NULL; 1735 } 1736 } 1737 1738 1739 1740 int 1741 telrcv() 1742 { 1743 register int c; 1744 register int scc; 1745 register unsigned char *sbp; 1746 int count; 1747 int returnValue = 0; 1748 int min_room = 0; 1749 1750 scc = 0; 1751 count = 0; 1752 while (--min_room > 2 || (min_room = TTYROOM()) > 2) { 1753 if (scc == 0) { 1754 if (count) { 1755 ring_consumed(&netiring, count); 1756 returnValue = 1; 1757 count = 0; 1758 } 1759 sbp = netiring.consume; 1760 scc = ring_full_consecutive(&netiring); 1761 if (scc == 0) { 1762 /* No more data coming in */ 1763 break; 1764 } 1765 } 1766 1767 c = *sbp++ & 0xff, scc--; count++; 1768 1769 if (decrypt_input) 1770 c = (*decrypt_input)(c); 1771 1772 switch (telrcv_state) { 1773 1774 case TS_CR: 1775 telrcv_state = TS_DATA; 1776 if (c == '\0') { 1777 break; /* Ignore \0 after CR */ 1778 } else if ((c == '\n') && 1779 my_want_state_is_dont(TELOPT_ECHO) && !crmod) { 1780 TTYADD(c); 1781 break; 1782 } 1783 /* FALLTHROUGH */ 1784 1785 case TS_DATA: 1786 if (c == IAC) { 1787 telrcv_state = TS_IAC; 1788 break; 1789 } 1790 /* 1791 * The 'crmod' hack (see following) is needed 1792 * since we can't * set CRMOD on output only. 1793 * Machines like MULTICS like to send \r without 1794 * \n; since we must turn off CRMOD to get proper 1795 * input, the mapping is done here (sigh). 1796 */ 1797 if ((c == '\r') && 1798 my_want_state_is_dont(TELOPT_BINARY)) { 1799 if (scc > 0) { 1800 c = *sbp&0xff; 1801 1802 if (decrypt_input) 1803 c = (*decrypt_input)(c); 1804 1805 if (c == 0) { 1806 sbp++, scc--; count++; 1807 /* a "true" CR */ 1808 TTYADD('\r'); 1809 } else if (my_want_state_is_dont( 1810 TELOPT_ECHO) && (c == '\n')) { 1811 sbp++, scc--; count++; 1812 TTYADD('\n'); 1813 } else { 1814 1815 if (decrypt_input) 1816 (*decrypt_input)(-1); 1817 1818 TTYADD('\r'); 1819 if (crmod) { 1820 TTYADD('\n'); 1821 } 1822 } 1823 } else { 1824 telrcv_state = TS_CR; 1825 TTYADD('\r'); 1826 if (crmod) { 1827 TTYADD('\n'); 1828 } 1829 } 1830 } else { 1831 TTYADD(c); 1832 } 1833 continue; 1834 1835 case TS_IAC: 1836 process_iac: 1837 switch (c) { 1838 1839 case WILL: 1840 telrcv_state = TS_WILL; 1841 continue; 1842 1843 case WONT: 1844 telrcv_state = TS_WONT; 1845 continue; 1846 1847 case DO: 1848 telrcv_state = TS_DO; 1849 continue; 1850 1851 case DONT: 1852 telrcv_state = TS_DONT; 1853 continue; 1854 1855 case DM: 1856 /* 1857 * We may have missed an urgent notification, 1858 * so make sure we flush whatever is in the 1859 * buffer currently. 1860 */ 1861 printoption("RCVD", IAC, DM); 1862 SYNCHing = 1; 1863 if (ttyflush(1) == -2) { 1864 /* This will not return. */ 1865 fatal_tty_error("write"); 1866 } 1867 SYNCHing = stilloob(); 1868 settimer(gotDM); 1869 break; 1870 1871 case SB: 1872 SB_CLEAR(); 1873 telrcv_state = TS_SB; 1874 continue; 1875 1876 case IAC: 1877 TTYADD(IAC); 1878 break; 1879 1880 case NOP: 1881 case GA: 1882 default: 1883 printoption("RCVD", IAC, c); 1884 break; 1885 } 1886 telrcv_state = TS_DATA; 1887 continue; 1888 1889 case TS_WILL: 1890 printoption("RCVD", WILL, c); 1891 willoption(c); 1892 telrcv_state = TS_DATA; 1893 continue; 1894 1895 case TS_WONT: 1896 printoption("RCVD", WONT, c); 1897 wontoption(c); 1898 telrcv_state = TS_DATA; 1899 continue; 1900 1901 case TS_DO: 1902 printoption("RCVD", DO, c); 1903 dooption(c); 1904 if (c == TELOPT_NAWS) { 1905 sendnaws(); 1906 } else if (c == TELOPT_LFLOW) { 1907 localflow = 1; 1908 setcommandmode(); 1909 setconnmode(0); 1910 } 1911 telrcv_state = TS_DATA; 1912 continue; 1913 1914 case TS_DONT: 1915 printoption("RCVD", DONT, c); 1916 dontoption(c); 1917 flushline = 1; 1918 setconnmode(0); /* set new tty mode (maybe) */ 1919 telrcv_state = TS_DATA; 1920 continue; 1921 1922 case TS_SB: 1923 if (c == IAC) { 1924 telrcv_state = TS_SE; 1925 } else { 1926 SB_ACCUM(c); 1927 } 1928 continue; 1929 1930 case TS_SE: 1931 if (c != SE) { 1932 if (c != IAC) { 1933 /* 1934 * This is an error. We only expect to get 1935 * "IAC IAC" or "IAC SE". Several things may 1936 * have happend. An IAC was not doubled, the 1937 * IAC SE was left off, or another option got 1938 * inserted into the suboption are all possibilities. 1939 * If we assume that the IAC was not doubled, 1940 * and really the IAC SE was left off, we could 1941 * get into an infinate loop here. So, instead, 1942 * we terminate the suboption, and process the 1943 * partial suboption if we can. 1944 */ 1945 SB_ACCUM(IAC); 1946 SB_ACCUM(c); 1947 subpointer -= 2; 1948 SB_TERM(); 1949 1950 printoption("In SUBOPTION processing, " 1951 "RCVD", IAC, c); 1952 suboption(); /* handle sub-option */ 1953 telrcv_state = TS_IAC; 1954 goto process_iac; 1955 } 1956 SB_ACCUM(c); 1957 telrcv_state = TS_SB; 1958 } else { 1959 SB_ACCUM(IAC); 1960 SB_ACCUM(SE); 1961 subpointer -= 2; 1962 SB_TERM(); 1963 suboption(); /* handle sub-option */ 1964 telrcv_state = TS_DATA; 1965 } 1966 } 1967 } 1968 if (count) 1969 ring_consumed(&netiring, count); 1970 return (returnValue||count); 1971 } 1972 1973 static int bol = 1, local = 0; 1974 1975 int 1976 rlogin_susp() 1977 { 1978 if (local) { 1979 local = 0; 1980 bol = 1; 1981 command(0, "z\n", 2); 1982 return (1); 1983 } 1984 return (0); 1985 } 1986 1987 static int 1988 telsnd() 1989 { 1990 int tcc; 1991 int count; 1992 int returnValue = 0; 1993 unsigned char *tbp; 1994 1995 tcc = 0; 1996 count = 0; 1997 while (NETROOM() > 2) { 1998 register int sc; 1999 register int c; 2000 2001 if (tcc == 0) { 2002 if (count) { 2003 ring_consumed(&ttyiring, count); 2004 returnValue = 1; 2005 count = 0; 2006 } 2007 tbp = ttyiring.consume; 2008 tcc = ring_full_consecutive(&ttyiring); 2009 if (tcc == 0) { 2010 break; 2011 } 2012 } 2013 c = *tbp++ & 0xff, sc = strip(c), tcc--; count++; 2014 if (rlogin != _POSIX_VDISABLE) { 2015 if (bol) { 2016 bol = 0; 2017 if (sc == rlogin) { 2018 local = 1; 2019 continue; 2020 } 2021 } else if (local) { 2022 local = 0; 2023 if (sc == '.' || c == termEofChar) { 2024 bol = 1; 2025 command(0, "close\n", 6); 2026 continue; 2027 } 2028 if (sc == termSuspChar) { 2029 bol = 1; 2030 command(0, "z\n", 2); 2031 continue; 2032 } 2033 if (sc == escape) { 2034 command(0, (char *)tbp, tcc); 2035 bol = 1; 2036 count += tcc; 2037 tcc = 0; 2038 flushline = 1; 2039 break; 2040 } 2041 if (sc != rlogin) { 2042 ++tcc; 2043 --tbp; 2044 --count; 2045 c = sc = rlogin; 2046 } 2047 } 2048 if ((sc == '\n') || (sc == '\r')) 2049 bol = 1; 2050 } else if (sc == escape && escape_valid) { 2051 /* 2052 * Double escape is a pass through of a single 2053 * escape character. 2054 */ 2055 if (tcc && strip(*tbp) == escape) { 2056 tbp++; 2057 tcc--; 2058 count++; 2059 bol = 0; 2060 } else { 2061 command(0, (char *)tbp, tcc); 2062 bol = 1; 2063 count += tcc; 2064 tcc = 0; 2065 flushline = 1; 2066 break; 2067 } 2068 } else 2069 bol = 0; 2070 #ifdef KLUDGELINEMODE 2071 if (kludgelinemode && (globalmode&MODE_EDIT) && (sc == echoc)) { 2072 if (tcc > 0 && strip(*tbp) == echoc) { 2073 tcc--; tbp++; count++; 2074 } else { 2075 dontlecho = !dontlecho; 2076 settimer(echotoggle); 2077 setconnmode(0); 2078 flushline = 1; 2079 break; 2080 } 2081 } 2082 #endif 2083 if (MODE_LOCAL_CHARS(globalmode)) { 2084 if (TerminalSpecialChars(sc) == 0) { 2085 bol = 1; 2086 break; 2087 } 2088 } 2089 if (my_want_state_is_wont(TELOPT_BINARY)) { 2090 switch (c) { 2091 case '\n': 2092 /* 2093 * If we are in CRMOD mode (\r ==> \n) 2094 * on our local machine, then probably 2095 * a newline (unix) is CRLF (TELNET). 2096 */ 2097 if (MODE_LOCAL_CHARS(globalmode)) { 2098 NETADD('\r'); 2099 } 2100 NETADD('\n'); 2101 bol = flushline = 1; 2102 break; 2103 case '\r': 2104 if (!crlf) { 2105 NET2ADD('\r', '\0'); 2106 } else { 2107 NET2ADD('\r', '\n'); 2108 } 2109 bol = flushline = 1; 2110 break; 2111 case IAC: 2112 NET2ADD(IAC, IAC); 2113 break; 2114 default: 2115 NETADD(c); 2116 break; 2117 } 2118 } else if (c == IAC) { 2119 NET2ADD(IAC, IAC); 2120 } else { 2121 NETADD(c); 2122 } 2123 } 2124 if (count) 2125 ring_consumed(&ttyiring, count); 2126 return (returnValue||count); /* Non-zero if we did anything */ 2127 } 2128 2129 /* 2130 * Scheduler() 2131 * 2132 * Try to do something. 2133 * 2134 * If we do something useful, return 1; else return 0. 2135 * 2136 */ 2137 2138 2139 int 2140 Scheduler(block) 2141 int block; /* should we block in the select ? */ 2142 { 2143 /* 2144 * One wants to be a bit careful about setting returnValue 2145 * to one, since a one implies we did some useful work, 2146 * and therefore probably won't be called to block next 2147 * time (TN3270 mode only). 2148 */ 2149 int returnValue; 2150 int netin, netout, netex, ttyin, ttyout; 2151 2152 /* Decide which rings should be processed */ 2153 2154 netout = ring_full_count(&netoring) && 2155 (flushline || 2156 (my_want_state_is_wont(TELOPT_LINEMODE) 2157 #ifdef KLUDGELINEMODE 2158 /* X */ && (!kludgelinemode || my_want_state_is_do(TELOPT_SGA)) 2159 #endif 2160 /* XXX */) || 2161 my_want_state_is_will(TELOPT_BINARY)); 2162 ttyout = ring_full_count(&ttyoring); 2163 2164 ttyin = (ring_empty_count(&ttyiring) && !eof_pending); 2165 2166 netin = !ISend && ring_empty_count(&netiring); 2167 2168 netex = !SYNCHing; 2169 2170 if (scheduler_lockout_tty) { 2171 ttyin = ttyout = 0; 2172 } 2173 2174 /* Call to system code to process rings */ 2175 2176 returnValue = process_rings(netin, netout, netex, ttyin, ttyout, 2177 !block); 2178 2179 /* Now, look at the input rings, looking for work to do. */ 2180 2181 if (ring_full_count(&ttyiring)) { 2182 returnValue |= telsnd(); 2183 } else { 2184 /* 2185 * If ttyiring is empty, check to see if there is a real EOF 2186 * pending. If so, we can maybe do the EOF write now. 2187 */ 2188 if (eof_pending) { 2189 eof_pending = 0; 2190 sendeof(); 2191 } 2192 } 2193 2194 if (ring_full_count(&netiring)) { 2195 returnValue |= telrcv(); 2196 } 2197 return (returnValue); 2198 } 2199 2200 /* 2201 * Select from tty and network... 2202 */ 2203 void 2204 telnet(user) 2205 char *user; 2206 { 2207 sys_telnet_init(); 2208 2209 { 2210 static char local_host[MAXHOSTNAMELEN] = { 0 }; 2211 2212 if (!local_host[0]) { 2213 (void) gethostname(local_host, sizeof (local_host)); 2214 local_host[sizeof (local_host)-1] = 0; 2215 } 2216 auth_encrypt_init(local_host, hostname, "TELNET"); 2217 auth_encrypt_user(user); 2218 } 2219 2220 if (autologin) 2221 send_will(TELOPT_AUTHENTICATION, 1); 2222 2223 if (telnetport || wantencryption) { 2224 send_do(TELOPT_ENCRYPT, 1); 2225 send_will(TELOPT_ENCRYPT, 1); 2226 } 2227 2228 if (telnetport) { 2229 if (!reqd_linemode) 2230 send_do(TELOPT_SGA, 1); 2231 send_will(TELOPT_TTYPE, 1); 2232 send_will(TELOPT_NAWS, 1); 2233 send_will(TELOPT_TSPEED, 1); 2234 send_will(TELOPT_LFLOW, 1); 2235 if (!reqd_linemode) 2236 send_will(TELOPT_LINEMODE, 1); 2237 send_will(TELOPT_NEW_ENVIRON, 1); 2238 send_do(TELOPT_STATUS, 1); 2239 if (env_getvalue((unsigned char *)"DISPLAY")) 2240 send_will(TELOPT_XDISPLOC, 1); 2241 if (eight) 2242 tel_enter_binary(eight); 2243 } 2244 2245 /* 2246 * Note: we assume a tie to the authentication option here. This 2247 * is necessary so that authentication fails, we don't spin 2248 * forever. 2249 */ 2250 if (wantencryption) { 2251 boolean_t printed_encrypt = B_FALSE; 2252 extern boolean_t auth_has_failed; 2253 time_t timeout = time(0) + 60; 2254 2255 send_do(TELOPT_ENCRYPT, 1); 2256 send_will(TELOPT_ENCRYPT, 1); 2257 for (;;) { 2258 if (my_want_state_is_wont(TELOPT_AUTHENTICATION)) { 2259 (void) printf(gettext( 2260 "\nServer refused to negotiate " 2261 "authentication, which is required\n" 2262 "for encryption. Good-bye.\n\r")); 2263 Exit(EXIT_FAILURE); 2264 } 2265 if (auth_has_failed) { 2266 (void) printf(gettext( 2267 "\nAuthentication negotation has failed, " 2268 "which is required for\n" 2269 "encryption. Good-bye.\n\r")); 2270 Exit(EXIT_FAILURE); 2271 } 2272 if (my_want_state_is_dont(TELOPT_ENCRYPT) || 2273 my_want_state_is_wont(TELOPT_ENCRYPT)) { 2274 (void) printf(gettext( 2275 "\nServer refused to negotiate encryption. " 2276 "Good-bye.\n\r")); 2277 Exit(EXIT_FAILURE); 2278 } 2279 if (encrypt_is_encrypting()) 2280 break; 2281 2282 if (time(0) > timeout) { 2283 (void) printf(gettext( 2284 "\nEncryption could not be enabled. " 2285 "Good-bye.\n\r")); 2286 Exit(EXIT_FAILURE); 2287 } 2288 if (printed_encrypt == B_FALSE) { 2289 printed_encrypt = B_TRUE; 2290 (void) printf(gettext( 2291 "Waiting for encryption to be negotiated...\n")); 2292 /* 2293 * Turn on MODE_TRAPSIG and then turn off localchars 2294 * so that ^C will cause telnet to exit. 2295 */ 2296 TerminalNewMode(getconnmode()|MODE_TRAPSIG); 2297 intr_waiting = 1; 2298 } 2299 if (intr_happened) { 2300 (void) printf(gettext( 2301 "\nUser requested an interrupt. Good-bye.\n\r")); 2302 Exit(EXIT_FAILURE); 2303 } 2304 telnet_spin(); 2305 } 2306 if (printed_encrypt) { 2307 (void) printf(gettext("done.\n")); 2308 intr_waiting = 0; 2309 setconnmode(0); 2310 } 2311 } 2312 2313 for (;;) { 2314 int schedValue; 2315 2316 while ((schedValue = Scheduler(0)) != 0) { 2317 if (schedValue == -1) { 2318 setcommandmode(); 2319 return; 2320 } 2321 } 2322 2323 if (Scheduler(1) == -1) { 2324 setcommandmode(); 2325 return; 2326 } 2327 } 2328 } 2329 2330 #if 0 /* XXX - this not being in is a bug */ 2331 /* 2332 * nextitem() 2333 * 2334 * Return the address of the next "item" in the TELNET data 2335 * stream. This will be the address of the next character if 2336 * the current address is a user data character, or it will 2337 * be the address of the character following the TELNET command 2338 * if the current address is a TELNET IAC ("I Am a Command") 2339 * character. 2340 */ 2341 2342 static char * 2343 nextitem(current) 2344 char *current; 2345 { 2346 if ((*current&0xff) != IAC) { 2347 return (current+1); 2348 } 2349 switch (*(current+1)&0xff) { 2350 case DO: 2351 case DONT: 2352 case WILL: 2353 case WONT: 2354 return (current+3); 2355 case SB: /* loop forever looking for the SE */ 2356 { 2357 register char *look = current+2; 2358 2359 for (;;) { 2360 if ((*look++&0xff) == IAC) { 2361 if ((*look++&0xff) == SE) { 2362 return (look); 2363 } 2364 } 2365 } 2366 } 2367 default: 2368 return (current+2); 2369 } 2370 } 2371 #endif /* 0 */ 2372 2373 /* 2374 * netclear() 2375 * 2376 * We are about to do a TELNET SYNCH operation. Clear 2377 * the path to the network. 2378 * 2379 * Things are a bit tricky since we may have sent the first 2380 * byte or so of a previous TELNET command into the network. 2381 * So, we have to scan the network buffer from the beginning 2382 * until we are up to where we want to be. 2383 * 2384 * A side effect of what we do, just to keep things 2385 * simple, is to clear the urgent data pointer. The principal 2386 * caller should be setting the urgent data pointer AFTER calling 2387 * us in any case. 2388 */ 2389 2390 static void 2391 netclear() 2392 { 2393 #if 0 /* XXX */ 2394 register char *thisitem, *next; 2395 char *good; 2396 #define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \ 2397 ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL)) 2398 2399 thisitem = netobuf; 2400 2401 while ((next = nextitem(thisitem)) <= netobuf.send) { 2402 thisitem = next; 2403 } 2404 2405 /* Now, thisitem is first before/at boundary. */ 2406 2407 good = netobuf; /* where the good bytes go */ 2408 2409 while (netoring.add > thisitem) { 2410 if (wewant(thisitem)) { 2411 int length; 2412 2413 next = thisitem; 2414 do { 2415 next = nextitem(next); 2416 } while (wewant(next) && (nfrontp > next)); 2417 length = next-thisitem; 2418 memcpy(good, thisitem, length); 2419 good += length; 2420 thisitem = next; 2421 } else { 2422 thisitem = nextitem(thisitem); 2423 } 2424 } 2425 2426 #endif /* 0 */ 2427 } 2428 2429 /* 2430 * These routines add various telnet commands to the data stream. 2431 */ 2432 2433 /* 2434 * doflush - Send do timing mark (for network connection flush) & then 2435 * get rid of anything in the output buffer. Return -1 if there was a 2436 * non-EWOULDBLOCK error on the tty flush, and otherwise return 0. 2437 */ 2438 static int 2439 doflush() 2440 { 2441 NET2ADD(IAC, DO); 2442 NETADD(TELOPT_TM); 2443 flushline = 1; 2444 flushout = 1; 2445 2446 /* Drop pending tty output */ 2447 if (ttyflush(1) == -2) 2448 return (-1); 2449 2450 /* do printoption AFTER flush, otherwise the output gets tossed... */ 2451 printoption("SENT", DO, TELOPT_TM); 2452 return (0); 2453 } 2454 2455 int 2456 xmitAO() 2457 { 2458 NET2ADD(IAC, AO); 2459 printoption("SENT", IAC, AO); 2460 if (autoflush) { 2461 if (doflush() == -1) 2462 return (-1); 2463 } 2464 return (0); 2465 } 2466 2467 2468 void 2469 xmitEL() 2470 { 2471 NET2ADD(IAC, EL); 2472 printoption("SENT", IAC, EL); 2473 } 2474 2475 void 2476 xmitEC() 2477 { 2478 NET2ADD(IAC, EC); 2479 printoption("SENT", IAC, EC); 2480 } 2481 2482 2483 int 2484 dosynch() 2485 { 2486 netclear(); /* clear the path to the network */ 2487 NETADD(IAC); 2488 setneturg(); 2489 NETADD(DM); 2490 printoption("SENT", IAC, DM); 2491 return (1); 2492 } 2493 2494 int want_status_response = 0; 2495 2496 int 2497 get_status() 2498 { 2499 unsigned char tmp[16]; 2500 register unsigned char *cp; 2501 2502 if (my_want_state_is_dont(TELOPT_STATUS)) { 2503 (void) printf("Remote side does not support STATUS option\n"); 2504 return (0); 2505 } 2506 cp = tmp; 2507 2508 *cp++ = IAC; 2509 *cp++ = SB; 2510 *cp++ = TELOPT_STATUS; 2511 *cp++ = TELQUAL_SEND; 2512 *cp++ = IAC; 2513 *cp++ = SE; 2514 if (NETROOM() >= cp - tmp) { 2515 ring_supply_data(&netoring, tmp, cp-tmp); 2516 printsub('>', tmp+2, cp - tmp - 2); 2517 } 2518 ++want_status_response; 2519 return (1); 2520 } 2521 2522 void 2523 intp() 2524 { 2525 NET2ADD(IAC, IP); 2526 printoption("SENT", IAC, IP); 2527 flushline = 1; 2528 if (autoflush) { 2529 /* Ignore return as we're ending off anyway. */ 2530 (void) doflush(); 2531 } 2532 if (autosynch) { 2533 (void) dosynch(); 2534 } 2535 } 2536 2537 int 2538 sendbrk() 2539 { 2540 NET2ADD(IAC, BREAK); 2541 printoption("SENT", IAC, BREAK); 2542 flushline = 1; 2543 if (autoflush) { 2544 if (doflush() == -1) 2545 return (-1); 2546 } 2547 if (autosynch) { 2548 (void) dosynch(); 2549 } 2550 return (0); 2551 } 2552 2553 void 2554 sendabort() 2555 { 2556 NET2ADD(IAC, ABORT); 2557 printoption("SENT", IAC, ABORT); 2558 flushline = 1; 2559 if (autoflush) { 2560 /* 2561 * Since sendabort() gets called while aborting, 2562 * ignore the doflush() return 2563 */ 2564 (void) doflush(); 2565 } 2566 if (autosynch) { 2567 (void) dosynch(); 2568 } 2569 } 2570 2571 void 2572 sendsusp() 2573 { 2574 NET2ADD(IAC, SUSP); 2575 printoption("SENT", IAC, SUSP); 2576 flushline = 1; 2577 if (autoflush) { 2578 if (doflush() == -1) { 2579 /* The following will not return. */ 2580 fatal_tty_error("write"); 2581 } 2582 } 2583 if (autosynch) { 2584 (void) dosynch(); 2585 } 2586 } 2587 2588 static void 2589 sendeof() 2590 { 2591 NET2ADD(IAC, xEOF); 2592 printoption("SENT", IAC, xEOF); 2593 } 2594 2595 /* 2596 * Send a window size update to the remote system. 2597 */ 2598 2599 void 2600 sendnaws() 2601 { 2602 unsigned short rows, cols; 2603 unsigned char tmp[16]; 2604 register unsigned char *cp; 2605 2606 if (my_state_is_wont(TELOPT_NAWS)) 2607 return; 2608 2609 #define PUTSHORT(cp, x) { if ((*cp++ = ((x)>>8)&0xff) == IAC) *cp++ = IAC; \ 2610 if ((*cp++ = ((x))&0xff) == IAC) *cp++ = IAC; } 2611 2612 if (TerminalWindowSize(&rows, &cols) == 0) { /* Failed */ 2613 return; 2614 } 2615 2616 cp = tmp; 2617 2618 *cp++ = IAC; 2619 *cp++ = SB; 2620 *cp++ = TELOPT_NAWS; 2621 PUTSHORT(cp, cols); 2622 PUTSHORT(cp, rows); 2623 *cp++ = IAC; 2624 *cp++ = SE; 2625 if (NETROOM() >= cp - tmp) { 2626 ring_supply_data(&netoring, tmp, cp-tmp); 2627 printsub('>', tmp+2, cp - tmp - 2); 2628 } 2629 } 2630 2631 void 2632 tel_enter_binary(rw) 2633 int rw; 2634 { 2635 if (rw&1) 2636 send_do(TELOPT_BINARY, 1); 2637 if (rw&2) 2638 send_will(TELOPT_BINARY, 1); 2639 } 2640 2641 void 2642 tel_leave_binary(rw) 2643 int rw; 2644 { 2645 if (rw&1) 2646 send_dont(TELOPT_BINARY, 1); 2647 if (rw&2) 2648 send_wont(TELOPT_BINARY, 1); 2649 } 2650