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