1 /* $NetBSD: telnetd.c,v 1.32 2002/01/31 07:54:50 itojun Exp $ */ 2 3 /* 4 * Copyright (C) 1997 and 1998 WIDE Project. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the project nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 /* 33 * Copyright (c) 1989, 1993 34 * The Regents of the University of California. All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. All advertising materials mentioning features or use of this software 45 * must display the following acknowledgement: 46 * This product includes software developed by the University of 47 * California, Berkeley and its contributors. 48 * 4. Neither the name of the University nor the names of its contributors 49 * may be used to endorse or promote products derived from this software 50 * without specific prior written permission. 51 * 52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62 * SUCH DAMAGE. 63 */ 64 65 #include <sys/cdefs.h> 66 #ifndef lint 67 __COPYRIGHT("@(#) Copyright (c) 1989, 1993\n\ 68 The Regents of the University of California. All rights reserved.\n"); 69 #if 0 70 static char sccsid[] = "@(#)telnetd.c 8.4 (Berkeley) 5/30/95"; 71 #else 72 __RCSID("$NetBSD: telnetd.c,v 1.32 2002/01/31 07:54:50 itojun Exp $"); 73 #endif 74 #endif /* not lint */ 75 76 #include "telnetd.h" 77 #include "pathnames.h" 78 79 #include <arpa/inet.h> 80 81 #include <err.h> 82 #include <termcap.h> 83 84 #include <limits.h> 85 86 #define P __P 87 88 #if defined(_SC_CRAY_SECURE_SYS) && !defined(SCM_SECURITY) 89 /* 90 * UNICOS 6.0/6.1 do not have SCM_SECURITY defined, so we can 91 * use it to tell us to turn off all the socket security code, 92 * since that is only used in UNICOS 7.0 and later. 93 */ 94 # undef _SC_CRAY_SECURE_SYS 95 #endif 96 97 #if defined(_SC_CRAY_SECURE_SYS) 98 #include <sys/sysv.h> 99 #include <sys/secdev.h> 100 # ifdef SO_SEC_MULTI /* 8.0 code */ 101 #include <sys/secparm.h> 102 #include <sys/usrv.h> 103 # endif /* SO_SEC_MULTI */ 104 int secflag; 105 char tty_dev[16]; 106 struct secdev dv; 107 struct sysv sysv; 108 # ifdef SO_SEC_MULTI /* 8.0 code */ 109 struct socksec ss; 110 # else /* SO_SEC_MULTI */ /* 7.0 code */ 111 struct socket_security ss; 112 # endif /* SO_SEC_MULTI */ 113 #endif /* _SC_CRAY_SECURE_SYS */ 114 115 #if defined(KRB5) 116 #define Authenticator k5_Authenticator 117 #include <krb5.h> 118 #undef Authenticator 119 #include <com_err.h> 120 #endif 121 122 #if defined(AUTHENTICATION) 123 int auth_level = 0; 124 #endif 125 126 #if defined(AUTHENTICATION) || defined(ENCRYPTION) 127 #include <libtelnet/misc.h> 128 #endif 129 130 #if defined(SECURELOGIN) 131 int require_secure_login = 0; 132 #endif 133 134 extern int utmp_len; 135 extern int require_hwpreauth; 136 #ifdef KRB5 137 extern krb5_context telnet_context; 138 #endif 139 int registerd_host_only = 0; 140 141 #ifdef STREAMSPTY 142 # include <stropts.h> 143 # include <termio.h> 144 /* make sure we don't get the bsd version */ 145 # include "/usr/include/sys/tty.h" 146 # include <sys/ptyvar.h> 147 148 /* 149 * Because of the way ptyibuf is used with streams messages, we need 150 * ptyibuf+1 to be on a full-word boundary. The following weirdness 151 * is simply to make that happen. 152 */ 153 long ptyibufbuf[BUFSIZ/sizeof(long)+1]; 154 char *ptyibuf = ((char *)&ptyibufbuf[1])-1; 155 char *ptyip = ((char *)&ptyibufbuf[1])-1; 156 char ptyibuf2[BUFSIZ*4]; 157 unsigned char ctlbuf[BUFSIZ]; 158 struct strbuf strbufc, strbufd; 159 160 int readstream(); 161 162 #else /* ! STREAMPTY */ 163 164 /* 165 * I/O data buffers, 166 * pointers, and counters. 167 */ 168 char ptyibuf[BUFSIZ], *ptyip = ptyibuf; 169 char ptyibuf2[BUFSIZ]; 170 171 #endif /* ! STREAMPTY */ 172 173 int hostinfo = 1; /* do we print login banner? */ 174 175 #ifdef CRAY 176 extern int newmap; /* nonzero if \n maps to ^M^J */ 177 int lowpty = 0, highpty; /* low, high pty numbers */ 178 #endif /* CRAY */ 179 180 int debug = 0; 181 int keepalive = 1; 182 char *gettyname = "default"; 183 char *progname; 184 185 int main __P((int, char *[])); 186 void usage __P((void)); 187 int getterminaltype __P((char *)); 188 int getent __P((char *, char *)); 189 void doit __P((struct sockaddr *)); 190 void _gettermname __P((void)); 191 int terminaltypeok __P((char *)); 192 char *getstr __P((const char *, char **)); 193 194 /* 195 * The string to pass to getopt(). We do it this way so 196 * that only the actual options that we support will be 197 * passed off to getopt(). 198 */ 199 char valid_opts[] = { 200 'd', ':', 'g', ':', 'h', 'k', 'n', 'S', ':', 'u', ':', 'U', 201 '4', '6', 202 #ifdef AUTHENTICATION 203 'a', ':', 'X', ':', 204 #endif 205 #ifdef BFTPDAEMON 206 'B', 207 #endif 208 #ifdef ENCRYPTION 209 'e', ':', 210 #endif 211 #ifdef DIAGNOSTICS 212 'D', ':', 213 #endif 214 #ifdef LINEMODE 215 'l', 216 #endif 217 #ifdef CRAY 218 'r', ':', 219 #endif 220 #ifdef SECURELOGIN 221 's', 222 #endif 223 #ifdef KRB5 224 'R', ':', 'H', 225 #endif 226 '\0' 227 }; 228 229 int family = AF_INET; 230 231 int 232 main(argc, argv) 233 int argc; 234 char *argv[]; 235 { 236 struct sockaddr_storage from; 237 int on = 1, fromlen; 238 register int ch; 239 #if defined(IPPROTO_IP) && defined(IP_TOS) 240 int tos = -1; 241 #endif 242 243 pfrontp = pbackp = ptyobuf; 244 netip = netibuf; 245 nfrontp = nbackp = netobuf; 246 #ifdef ENCRYPTION 247 nclearto = 0; 248 #endif /* ENCRYPTION */ 249 250 progname = *argv; 251 252 #ifdef CRAY 253 /* 254 * Get number of pty's before trying to process options, 255 * which may include changing pty range. 256 */ 257 highpty = getnpty(); 258 #endif /* CRAY */ 259 260 while ((ch = getopt(argc, argv, valid_opts)) != -1) { 261 switch (ch) { 262 263 #ifdef AUTHENTICATION 264 case 'a': 265 /* 266 * Check for required authentication level 267 */ 268 if (strcmp(optarg, "debug") == 0) { 269 auth_debug_mode = 1; 270 } else if (strcasecmp(optarg, "none") == 0) { 271 auth_level = 0; 272 } else if (strcasecmp(optarg, "other") == 0) { 273 auth_level = AUTH_OTHER; 274 } else if (strcasecmp(optarg, "user") == 0) { 275 auth_level = AUTH_USER; 276 } else if (strcasecmp(optarg, "valid") == 0) { 277 auth_level = AUTH_VALID; 278 } else if (strcasecmp(optarg, "off") == 0) { 279 /* 280 * This hack turns off authentication 281 */ 282 auth_level = -1; 283 } else { 284 fprintf(stderr, 285 "telnetd: unknown authorization level for -a\n"); 286 } 287 break; 288 #endif /* AUTHENTICATION */ 289 290 #ifdef BFTPDAEMON 291 case 'B': 292 bftpd++; 293 break; 294 #endif /* BFTPDAEMON */ 295 296 case 'd': 297 if (strcmp(optarg, "ebug") == 0) { 298 debug++; 299 break; 300 } 301 usage(); 302 /* NOTREACHED */ 303 break; 304 305 #ifdef DIAGNOSTICS 306 case 'D': 307 /* 308 * Check for desired diagnostics capabilities. 309 */ 310 if (!strcmp(optarg, "report")) { 311 diagnostic |= TD_REPORT|TD_OPTIONS; 312 } else if (!strcmp(optarg, "exercise")) { 313 diagnostic |= TD_EXERCISE; 314 } else if (!strcmp(optarg, "netdata")) { 315 diagnostic |= TD_NETDATA; 316 } else if (!strcmp(optarg, "ptydata")) { 317 diagnostic |= TD_PTYDATA; 318 } else if (!strcmp(optarg, "options")) { 319 diagnostic |= TD_OPTIONS; 320 } else { 321 usage(); 322 /* NOT REACHED */ 323 } 324 break; 325 #endif /* DIAGNOSTICS */ 326 327 #ifdef ENCRYPTION 328 case 'e': 329 if (strcmp(optarg, "debug") == 0) { 330 encrypt_debug_mode = 1; 331 break; 332 } 333 usage(); 334 /* NOTREACHED */ 335 break; 336 #endif /* ENCRYPTION */ 337 338 case 'g': 339 gettyname = optarg; 340 break; 341 342 case 'h': 343 hostinfo = 0; 344 break; 345 346 #ifdef KRB5 347 case 'H': 348 { 349 require_hwpreauth = 1; 350 break; 351 } 352 #endif /* KRB5 */ 353 354 355 #ifdef LINEMODE 356 case 'l': 357 alwayslinemode = 1; 358 break; 359 #endif /* LINEMODE */ 360 361 case 'k': 362 #if defined(LINEMODE) && defined(KLUDGELINEMODE) 363 lmodetype = NO_AUTOKLUDGE; 364 #else 365 /* ignore -k option if built without kludge linemode */ 366 #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ 367 break; 368 369 case 'n': 370 keepalive = 0; 371 break; 372 373 #ifdef CRAY 374 case 'r': 375 { 376 char *strchr(); 377 char *c; 378 379 /* 380 * Allow the specification of alterations 381 * to the pty search range. It is legal to 382 * specify only one, and not change the 383 * other from its default. 384 */ 385 c = strchr(optarg, '-'); 386 if (c) { 387 *c++ = '\0'; 388 highpty = atoi(c); 389 } 390 if (*optarg != '\0') 391 lowpty = atoi(optarg); 392 if ((lowpty > highpty) || (lowpty < 0) || 393 (highpty > 32767)) { 394 usage(); 395 /* NOT REACHED */ 396 } 397 break; 398 } 399 #endif /* CRAY */ 400 401 #ifdef KRB5 402 case 'R': 403 { 404 krb5_error_code retval; 405 406 if (telnet_context == 0) { 407 retval = krb5_init_context(&telnet_context); 408 if (retval) { 409 com_err("telnetd", retval, 410 "while initializing krb5"); 411 exit(1); 412 } 413 } 414 krb5_set_default_realm(telnet_context, optarg); 415 break; 416 } 417 #endif /* KRB5 */ 418 419 #ifdef SECURELOGIN 420 case 's': 421 /* Secure login required */ 422 require_secure_login = 1; 423 break; 424 #endif /* SECURELOGIN */ 425 case 'S': 426 #ifdef HAS_GETTOS 427 if ((tos = parsetos(optarg, "tcp")) < 0) 428 fprintf(stderr, "%s%s%s\n", 429 "telnetd: Bad TOS argument '", optarg, 430 "'; will try to use default TOS"); 431 #else 432 fprintf(stderr, "%s%s\n", "TOS option unavailable; ", 433 "-S flag not supported\n"); 434 #endif 435 break; 436 437 case 'u': 438 utmp_len = atoi(optarg); 439 break; 440 441 case 'U': 442 registerd_host_only = 1; 443 break; 444 445 #ifdef AUTHENTICATION 446 case 'X': 447 /* 448 * Check for invalid authentication types 449 */ 450 auth_disable_name(optarg); 451 break; 452 #endif /* AUTHENTICATION */ 453 454 case '4': 455 family = AF_INET; 456 break; 457 458 case '6': 459 family = AF_INET6; 460 break; 461 462 default: 463 fprintf(stderr, "telnetd: %c: unknown option\n", ch); 464 /* FALLTHROUGH */ 465 case '?': 466 usage(); 467 /* NOTREACHED */ 468 } 469 } 470 471 argc -= optind; 472 argv += optind; 473 474 if (debug) { 475 int s, ns, foo, error; 476 char *service = "telnet"; 477 struct addrinfo hints, *res; 478 479 if (argc > 1) { 480 usage(); 481 /* NOT REACHED */ 482 } else if (argc == 1) 483 service = *argv; 484 485 memset(&hints, 0, sizeof(hints)); 486 hints.ai_flags = AI_PASSIVE; 487 hints.ai_family = family; 488 hints.ai_socktype = SOCK_STREAM; 489 hints.ai_protocol = 0; 490 error = getaddrinfo(NULL, service, &hints, &res); 491 492 if (error) { 493 fprintf(stderr, "tcp/%s: %s\n", service, gai_strerror(error)); 494 exit(1); 495 } 496 497 s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 498 if (s < 0) { 499 perror("telnetd: socket"); 500 exit(1); 501 } 502 (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, 503 (char *)&on, sizeof(on)); 504 if (bind(s, res->ai_addr, res->ai_addrlen) < 0) { 505 perror("bind"); 506 exit(1); 507 } 508 if (listen(s, 1) < 0) { 509 perror("listen"); 510 exit(1); 511 } 512 foo = res->ai_addrlen; 513 ns = accept(s, res->ai_addr, &foo); 514 if (ns < 0) { 515 perror("accept"); 516 exit(1); 517 } 518 (void) dup2(ns, 0); 519 (void) close(ns); 520 (void) close(s); 521 #ifdef convex 522 } else if (argc == 1) { 523 ; /* VOID*/ /* Just ignore the host/port name */ 524 #endif 525 } else if (argc > 0) { 526 usage(); 527 /* NOT REACHED */ 528 } 529 530 #if defined(_SC_CRAY_SECURE_SYS) 531 secflag = sysconf(_SC_CRAY_SECURE_SYS); 532 533 /* 534 * Get socket's security label 535 */ 536 if (secflag) { 537 int szss = sizeof(ss); 538 #ifdef SO_SEC_MULTI /* 8.0 code */ 539 int sock_multi; 540 int szi = sizeof(int); 541 #endif /* SO_SEC_MULTI */ 542 543 memset((char *)&dv, 0, sizeof(dv)); 544 545 if (getsysv(&sysv, sizeof(struct sysv)) != 0) { 546 perror("getsysv"); 547 exit(1); 548 } 549 550 /* 551 * Get socket security label and set device values 552 * {security label to be set on ttyp device} 553 */ 554 #ifdef SO_SEC_MULTI /* 8.0 code */ 555 if ((getsockopt(0, SOL_SOCKET, SO_SECURITY, 556 (char *)&ss, &szss) < 0) || 557 (getsockopt(0, SOL_SOCKET, SO_SEC_MULTI, 558 (char *)&sock_multi, &szi) < 0)) { 559 perror("getsockopt"); 560 exit(1); 561 } else { 562 dv.dv_actlvl = ss.ss_actlabel.lt_level; 563 dv.dv_actcmp = ss.ss_actlabel.lt_compart; 564 if (!sock_multi) { 565 dv.dv_minlvl = dv.dv_maxlvl = dv.dv_actlvl; 566 dv.dv_valcmp = dv.dv_actcmp; 567 } else { 568 dv.dv_minlvl = ss.ss_minlabel.lt_level; 569 dv.dv_maxlvl = ss.ss_maxlabel.lt_level; 570 dv.dv_valcmp = ss.ss_maxlabel.lt_compart; 571 } 572 dv.dv_devflg = 0; 573 } 574 #else /* SO_SEC_MULTI */ /* 7.0 code */ 575 if (getsockopt(0, SOL_SOCKET, SO_SECURITY, 576 (char *)&ss, &szss) >= 0) { 577 dv.dv_actlvl = ss.ss_slevel; 578 dv.dv_actcmp = ss.ss_compart; 579 dv.dv_minlvl = ss.ss_minlvl; 580 dv.dv_maxlvl = ss.ss_maxlvl; 581 dv.dv_valcmp = ss.ss_maxcmp; 582 } 583 #endif /* SO_SEC_MULTI */ 584 } 585 #endif /* _SC_CRAY_SECURE_SYS */ 586 587 openlog("telnetd", LOG_PID, LOG_DAEMON); 588 fromlen = sizeof (from); 589 if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { 590 fprintf(stderr, "%s: ", progname); 591 perror("getpeername"); 592 _exit(1); 593 } 594 if (keepalive && 595 setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, 596 (char *)&on, sizeof (on)) < 0) { 597 syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); 598 } 599 600 #if defined(IPPROTO_IP) && defined(IP_TOS) 601 if (((struct sockaddr *)&from)->sa_family == AF_INET) { 602 # if defined(HAS_GETTOS) 603 struct tosent *tp; 604 if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) 605 tos = tp->t_tos; 606 # endif 607 if (tos < 0) 608 tos = 020; /* Low Delay bit */ 609 if (tos 610 && (setsockopt(0, IPPROTO_IP, IP_TOS, 611 (char *)&tos, sizeof(tos)) < 0) 612 && (errno != ENOPROTOOPT) ) 613 syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); 614 } 615 #endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ 616 617 net = 0; 618 doit((struct sockaddr *)&from); 619 /* NOTREACHED */ 620 #ifdef __GNUC__ 621 exit(0); 622 #endif 623 } /* end of main */ 624 625 void 626 usage() 627 { 628 fprintf(stderr, "Usage: telnetd"); 629 #ifdef AUTHENTICATION 630 fprintf(stderr, " [-a (debug|other|user|valid|off|none)]\n\t"); 631 #endif 632 #ifdef BFTPDAEMON 633 fprintf(stderr, " [-B]"); 634 #endif 635 fprintf(stderr, " [-debug]"); 636 #ifdef DIAGNOSTICS 637 fprintf(stderr, " [-D (options|report|exercise|netdata|ptydata)]\n\t"); 638 #endif 639 #ifdef ENCRYPTION 640 fprintf(stderr, " [-edebug]"); 641 #endif 642 fprintf(stderr, " [-h]"); 643 #if defined(LINEMODE) && defined(KLUDGELINEMODE) 644 fprintf(stderr, " [-k]"); 645 #endif 646 #ifdef LINEMODE 647 fprintf(stderr, " [-l]"); 648 #endif 649 fprintf(stderr, " [-n]"); 650 #ifdef CRAY 651 fprintf(stderr, " [-r[lowpty]-[highpty]]"); 652 #endif 653 fprintf(stderr, "\n\t"); 654 #ifdef SECURELOGIN 655 fprintf(stderr, " [-s]"); 656 #endif 657 #ifdef HAS_GETTOS 658 fprintf(stderr, " [-S tos]"); 659 #endif 660 #ifdef AUTHENTICATION 661 fprintf(stderr, " [-X auth-type]"); 662 #endif 663 fprintf(stderr, " [-u utmp_hostname_length] [-U]"); 664 fprintf(stderr, " [port]\n"); 665 exit(1); 666 } 667 668 /* 669 * getterminaltype 670 * 671 * Ask the other end to send along its terminal type and speed. 672 * Output is the variable terminaltype filled in. 673 */ 674 static unsigned char ttytype_sbbuf[] = { 675 IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE 676 }; 677 678 int 679 getterminaltype(name) 680 char *name; 681 { 682 int retval = -1; 683 684 settimer(baseline); 685 #if defined(AUTHENTICATION) 686 /* 687 * Handle the Authentication option before we do anything else. 688 */ 689 send_do(TELOPT_AUTHENTICATION, 1); 690 while (his_will_wont_is_changing(TELOPT_AUTHENTICATION)) 691 ttloop(); 692 if (his_state_is_will(TELOPT_AUTHENTICATION)) { 693 retval = auth_wait(name); 694 } 695 #endif 696 697 #ifdef ENCRYPTION 698 send_will(TELOPT_ENCRYPT, 1); 699 #endif /* ENCRYPTION */ 700 send_do(TELOPT_TTYPE, 1); 701 send_do(TELOPT_TSPEED, 1); 702 send_do(TELOPT_XDISPLOC, 1); 703 send_do(TELOPT_NEW_ENVIRON, 1); 704 send_do(TELOPT_OLD_ENVIRON, 1); 705 while ( 706 #ifdef ENCRYPTION 707 his_do_dont_is_changing(TELOPT_ENCRYPT) || 708 #endif /* ENCRYPTION */ 709 his_will_wont_is_changing(TELOPT_TTYPE) || 710 his_will_wont_is_changing(TELOPT_TSPEED) || 711 his_will_wont_is_changing(TELOPT_XDISPLOC) || 712 his_will_wont_is_changing(TELOPT_NEW_ENVIRON) || 713 his_will_wont_is_changing(TELOPT_OLD_ENVIRON)) { 714 ttloop(); 715 } 716 if (his_state_is_will(TELOPT_TSPEED)) { 717 static unsigned char sb[] = 718 { IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE }; 719 720 output_datalen((const char *)sb, sizeof sb); 721 DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); 722 } 723 #ifdef ENCRYPTION 724 /* 725 * Wait for the negotiation of what type of encryption we can 726 * send with. If autoencrypt is not set, this will just return. 727 */ 728 if (his_state_is_will(TELOPT_ENCRYPT)) { 729 encrypt_wait(); 730 } 731 #endif /* ENCRYPTION */ 732 if (his_state_is_will(TELOPT_XDISPLOC)) { 733 static unsigned char sb[] = 734 { IAC, SB, TELOPT_XDISPLOC, TELQUAL_SEND, IAC, SE }; 735 736 output_datalen((const char *)sb, sizeof sb); 737 DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); 738 } 739 if (his_state_is_will(TELOPT_NEW_ENVIRON)) { 740 static unsigned char sb[] = 741 { IAC, SB, TELOPT_NEW_ENVIRON, TELQUAL_SEND, IAC, SE }; 742 743 output_datalen((const char *)sb, sizeof sb); 744 DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); 745 } 746 else if (his_state_is_will(TELOPT_OLD_ENVIRON)) { 747 static unsigned char sb[] = 748 { IAC, SB, TELOPT_OLD_ENVIRON, TELQUAL_SEND, IAC, SE }; 749 750 output_datalen((const char *)sb, sizeof sb); 751 DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); 752 } 753 if (his_state_is_will(TELOPT_TTYPE)) { 754 755 output_datalen((const char *)ttytype_sbbuf, sizeof ttytype_sbbuf); 756 DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2, 757 sizeof ttytype_sbbuf - 2);); 758 } 759 if (his_state_is_will(TELOPT_TSPEED)) { 760 while (sequenceIs(tspeedsubopt, baseline)) 761 ttloop(); 762 } 763 if (his_state_is_will(TELOPT_XDISPLOC)) { 764 while (sequenceIs(xdisplocsubopt, baseline)) 765 ttloop(); 766 } 767 if (his_state_is_will(TELOPT_NEW_ENVIRON)) { 768 while (sequenceIs(environsubopt, baseline)) 769 ttloop(); 770 } 771 if (his_state_is_will(TELOPT_OLD_ENVIRON)) { 772 while (sequenceIs(oenvironsubopt, baseline)) 773 ttloop(); 774 } 775 if (his_state_is_will(TELOPT_TTYPE)) { 776 char first[256], last[256]; 777 778 while (sequenceIs(ttypesubopt, baseline)) 779 ttloop(); 780 781 /* 782 * If the other side has already disabled the option, then 783 * we have to just go with what we (might) have already gotten. 784 */ 785 if (his_state_is_will(TELOPT_TTYPE) && !terminaltypeok(terminaltype)) { 786 (void) strncpy(first, terminaltype, sizeof(first) - 1); 787 first[sizeof(first) - 1] = '\0'; 788 for(;;) { 789 /* 790 * Save the unknown name, and request the next name. 791 */ 792 (void) strncpy(last, terminaltype, sizeof(last) - 1); 793 last[sizeof(last) - 1] = '\0'; 794 _gettermname(); 795 if (terminaltypeok(terminaltype)) 796 break; 797 if ((strncmp(last, terminaltype, sizeof(last)) == 0) || 798 his_state_is_wont(TELOPT_TTYPE)) { 799 /* 800 * We've hit the end. If this is the same as 801 * the first name, just go with it. 802 */ 803 if (strncmp(first, terminaltype, sizeof(first)) == 0) 804 break; 805 /* 806 * Get the terminal name one more time, so that 807 * RFC1091 compliant telnets will cycle back to 808 * the start of the list. 809 */ 810 _gettermname(); 811 if (strncmp(first, terminaltype, sizeof(first)) != 0) { 812 (void) strncpy(terminaltype, first, sizeof(first) - 1); 813 terminaltype[sizeof(terminaltype) - 1] = '\0'; 814 } 815 break; 816 } 817 } 818 } 819 } 820 return(retval); 821 } /* end of getterminaltype */ 822 823 void 824 _gettermname() 825 { 826 /* 827 * If the client turned off the option, 828 * we can't send another request, so we 829 * just return. 830 */ 831 if (his_state_is_wont(TELOPT_TTYPE)) 832 return; 833 settimer(baseline); 834 output_datalen((const char *)ttytype_sbbuf, sizeof ttytype_sbbuf); 835 DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2, 836 sizeof ttytype_sbbuf - 2);); 837 while (sequenceIs(ttypesubopt, baseline)) 838 ttloop(); 839 } 840 841 int 842 terminaltypeok(s) 843 char *s; 844 { 845 char buf[1024]; 846 847 if (terminaltype == NULL) 848 return(1); 849 850 /* 851 * tgetent() will return 1 if the type is known, and 852 * 0 if it is not known. If it returns -1, it couldn't 853 * open the database. But if we can't open the database, 854 * it won't help to say we failed, because we won't be 855 * able to verify anything else. So, we treat -1 like 1. 856 */ 857 if (tgetent(buf, s) == 0) 858 return(0); 859 return(1); 860 } 861 862 #ifndef MAXHOSTNAMELEN 863 #define MAXHOSTNAMELEN 64 864 #endif /* MAXHOSTNAMELEN */ 865 866 char *hostname; 867 char host_name[MAXHOSTNAMELEN + 1]; 868 char remote_host_name[MAXHOSTNAMELEN + 1]; 869 870 #ifndef convex 871 extern void telnet P((int, int)); 872 #else 873 extern void telnet P((int, int, char *)); 874 #endif 875 876 /* 877 * Get a pty, scan input lines. 878 */ 879 void 880 doit(who) 881 struct sockaddr *who; 882 { 883 char *host; 884 int error; 885 int level; 886 int ptynum; 887 char user_name[256]; 888 889 /* 890 * Find an available pty to use. 891 */ 892 #ifndef convex 893 pty = getpty(&ptynum); 894 if (pty < 0) 895 fatal(net, "All network ports in use"); 896 #else 897 for (;;) { 898 char *lp; 899 900 if ((lp = getpty()) == NULL) 901 fatal(net, "Out of ptys"); 902 903 if ((pty = open(lp, 2)) >= 0) { 904 (void)strlcpy(line, lp, sizeof(NULL16STR)); 905 line[5] = 't'; 906 break; 907 } 908 } 909 #endif 910 911 #if defined(_SC_CRAY_SECURE_SYS) 912 /* 913 * set ttyp line security label 914 */ 915 if (secflag) { 916 char slave_dev[16]; 917 918 sprintf(tty_dev, "/dev/pty/%03d", ptynum); 919 if (setdevs(tty_dev, &dv) < 0) 920 fatal(net, "cannot set pty security"); 921 sprintf(slave_dev, "/dev/ttyp%03d", ptynum); 922 if (setdevs(slave_dev, &dv) < 0) 923 fatal(net, "cannot set tty security"); 924 } 925 #endif /* _SC_CRAY_SECURE_SYS */ 926 927 /* get name of connected client */ 928 error = getnameinfo(who, who->sa_len, remote_host_name, 929 sizeof(remote_host_name), NULL, 0, 0); 930 931 if (!error && strlen(remote_host_name) > utmp_len) 932 error = getnameinfo(who, who->sa_len, remote_host_name, 933 sizeof(remote_host_name), NULL, 0, NI_NUMERICHOST); 934 935 if (error) { 936 fatal(net, "Couldn't resolve your address into a host name.\r\n\ 937 Please contact your net administrator"); 938 #ifdef __GNUC__ 939 host = NULL; /* XXX gcc */ 940 #endif 941 } 942 943 remote_host_name[sizeof(remote_host_name)-1] = 0; 944 host = remote_host_name; 945 946 (void)gethostname(host_name, sizeof (host_name)); 947 host_name[sizeof(host_name) - 1] = '\0'; 948 hostname = host_name; 949 950 #if defined(AUTHENTICATION) || defined(ENCRYPTION) 951 auth_encrypt_init(hostname, host, "TELNETD", 1); 952 #endif 953 954 init_env(); 955 /* 956 * get terminal type. 957 */ 958 *user_name = 0; 959 level = getterminaltype(user_name); 960 setenv("TERM", terminaltype ? terminaltype : "network", 1); 961 962 /* 963 * Start up the login process on the slave side of the terminal 964 */ 965 #ifndef convex 966 startslave(host, level, user_name); 967 968 #if defined(_SC_CRAY_SECURE_SYS) 969 if (secflag) { 970 if (setulvl(dv.dv_actlvl) < 0) 971 fatal(net,"cannot setulvl()"); 972 if (setucmp(dv.dv_actcmp) < 0) 973 fatal(net, "cannot setucmp()"); 974 } 975 #endif /* _SC_CRAY_SECURE_SYS */ 976 977 telnet(net, pty); /* begin server processing */ 978 #else 979 telnet(net, pty, host); 980 #endif 981 /*NOTREACHED*/ 982 } /* end of doit */ 983 984 985 /* 986 * Main loop. Select from pty and network, and 987 * hand data to telnet receiver finite state machine. 988 */ 989 void 990 #ifndef convex 991 telnet(f, p) 992 #else 993 telnet(f, p, host) 994 #endif 995 int f, p; 996 #ifdef convex 997 char *host; 998 #endif 999 { 1000 int on = 1; 1001 #define TABBUFSIZ 512 1002 char defent[TABBUFSIZ]; 1003 char defstrs[TABBUFSIZ]; 1004 #undef TABBUFSIZ 1005 char *HE, *HN, *IM, *IF, *ptyibuf2ptr; 1006 int nfd; 1007 1008 /* 1009 * Initialize the slc mapping table. 1010 */ 1011 get_slc_defaults(); 1012 1013 /* 1014 * Do some tests where it is desireable to wait for a response. 1015 * Rather than doing them slowly, one at a time, do them all 1016 * at once. 1017 */ 1018 if (my_state_is_wont(TELOPT_SGA)) 1019 send_will(TELOPT_SGA, 1); 1020 /* 1021 * Is the client side a 4.2 (NOT 4.3) system? We need to know this 1022 * because 4.2 clients are unable to deal with TCP urgent data. 1023 * 1024 * To find out, we send out a "DO ECHO". If the remote system 1025 * answers "WILL ECHO" it is probably a 4.2 client, and we note 1026 * that fact ("WILL ECHO" ==> that the client will echo what 1027 * WE, the server, sends it; it does NOT mean that the client will 1028 * echo the terminal input). 1029 */ 1030 send_do(TELOPT_ECHO, 1); 1031 1032 #ifdef LINEMODE 1033 if (his_state_is_wont(TELOPT_LINEMODE)) { 1034 /* Query the peer for linemode support by trying to negotiate 1035 * the linemode option. 1036 */ 1037 linemode = 0; 1038 editmode = 0; 1039 send_do(TELOPT_LINEMODE, 1); /* send do linemode */ 1040 } 1041 #endif /* LINEMODE */ 1042 1043 /* 1044 * Send along a couple of other options that we wish to negotiate. 1045 */ 1046 send_do(TELOPT_NAWS, 1); 1047 send_will(TELOPT_STATUS, 1); 1048 flowmode = 1; /* default flow control state */ 1049 restartany = -1; /* uninitialized... */ 1050 send_do(TELOPT_LFLOW, 1); 1051 1052 /* 1053 * Spin, waiting for a response from the DO ECHO. However, 1054 * some REALLY DUMB telnets out there might not respond 1055 * to the DO ECHO. So, we spin looking for NAWS, (most dumb 1056 * telnets so far seem to respond with WONT for a DO that 1057 * they don't understand...) because by the time we get the 1058 * response, it will already have processed the DO ECHO. 1059 * Kludge upon kludge. 1060 */ 1061 while (his_will_wont_is_changing(TELOPT_NAWS)) 1062 ttloop(); 1063 1064 /* 1065 * But... 1066 * The client might have sent a WILL NAWS as part of its 1067 * startup code; if so, we'll be here before we get the 1068 * response to the DO ECHO. We'll make the assumption 1069 * that any implementation that understands about NAWS 1070 * is a modern enough implementation that it will respond 1071 * to our DO ECHO request; hence we'll do another spin 1072 * waiting for the ECHO option to settle down, which is 1073 * what we wanted to do in the first place... 1074 */ 1075 if (his_want_state_is_will(TELOPT_ECHO) && 1076 his_state_is_will(TELOPT_NAWS)) { 1077 while (his_will_wont_is_changing(TELOPT_ECHO)) 1078 ttloop(); 1079 } 1080 /* 1081 * On the off chance that the telnet client is broken and does not 1082 * respond to the DO ECHO we sent, (after all, we did send the 1083 * DO NAWS negotiation after the DO ECHO, and we won't get here 1084 * until a response to the DO NAWS comes back) simulate the 1085 * receipt of a will echo. This will also send a WONT ECHO 1086 * to the client, since we assume that the client failed to 1087 * respond because it believes that it is already in DO ECHO 1088 * mode, which we do not want. 1089 */ 1090 if (his_want_state_is_will(TELOPT_ECHO)) { 1091 DIAG(TD_OPTIONS, 1092 {output_data("td: simulating recv\r\n");}); 1093 willoption(TELOPT_ECHO); 1094 } 1095 1096 /* 1097 * Finally, to clean things up, we turn on our echo. This 1098 * will break stupid 4.2 telnets out of local terminal echo. 1099 */ 1100 1101 if (my_state_is_wont(TELOPT_ECHO)) 1102 send_will(TELOPT_ECHO, 1); 1103 1104 #ifndef STREAMSPTY 1105 /* 1106 * Turn on packet mode 1107 */ 1108 (void) ioctl(p, TIOCPKT, (char *)&on); 1109 #endif 1110 1111 #if defined(LINEMODE) && defined(KLUDGELINEMODE) 1112 /* 1113 * Continuing line mode support. If client does not support 1114 * real linemode, attempt to negotiate kludge linemode by sending 1115 * the do timing mark sequence. 1116 */ 1117 if (lmodetype < REAL_LINEMODE) 1118 send_do(TELOPT_TM, 1); 1119 #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ 1120 1121 /* 1122 * Call telrcv() once to pick up anything received during 1123 * terminal type negotiation, 4.2/4.3 determination, and 1124 * linemode negotiation. 1125 */ 1126 telrcv(); 1127 1128 (void) ioctl(f, FIONBIO, (char *)&on); 1129 (void) ioctl(p, FIONBIO, (char *)&on); 1130 1131 #if defined(SO_OOBINLINE) 1132 (void) setsockopt(net, SOL_SOCKET, SO_OOBINLINE, 1133 (char *)&on, sizeof on); 1134 #endif /* defined(SO_OOBINLINE) */ 1135 1136 #ifdef SIGTSTP 1137 (void) signal(SIGTSTP, SIG_IGN); 1138 #endif 1139 #ifdef SIGTTOU 1140 /* 1141 * Ignoring SIGTTOU keeps the kernel from blocking us 1142 * in ttioct() in /sys/tty.c. 1143 */ 1144 (void) signal(SIGTTOU, SIG_IGN); 1145 #endif 1146 1147 (void) signal(SIGCHLD, cleanup); 1148 1149 1150 #ifdef TIOCNOTTY 1151 { 1152 register int t; 1153 t = open(_PATH_TTY, O_RDWR); 1154 if (t >= 0) { 1155 (void) ioctl(t, TIOCNOTTY, (char *)0); 1156 (void) close(t); 1157 } 1158 } 1159 #endif 1160 1161 1162 /* 1163 * Show banner that getty never gave. 1164 * 1165 * We put the banner in the pty input buffer. This way, it 1166 * gets carriage return null processing, etc., just like all 1167 * other pty --> client data. 1168 */ 1169 1170 if (getenv("USER")) 1171 hostinfo = 0; 1172 1173 if (getent(defent, gettyname) == 1) { 1174 char *cp=defstrs; 1175 1176 HE = getstr("he", &cp); 1177 HN = getstr("hn", &cp); 1178 IM = getstr("im", &cp); 1179 IF = getstr("if", &cp); 1180 if (HN && *HN) 1181 (void)strlcpy(host_name, HN, sizeof(host_name)); 1182 if (IM == 0) 1183 IM = ""; 1184 } else { 1185 IM = DEFAULT_IM; 1186 HE = 0; 1187 } 1188 edithost(HE, host_name); 1189 ptyibuf2ptr = ptyibuf2; 1190 if (hostinfo) { 1191 if (IF) { 1192 char buf[_POSIX2_LINE_MAX]; 1193 FILE *fd; 1194 1195 if ((fd = fopen(IF, "r")) != NULL) { 1196 while (fgets(buf, sizeof(buf) - 1, fd) != NULL) 1197 ptyibuf2ptr = putf(buf, ptyibuf2ptr); 1198 fclose(fd); 1199 } 1200 } 1201 if (*IM) 1202 ptyibuf2ptr = putf(IM, ptyibuf2ptr); 1203 } 1204 1205 if (pcc) 1206 strncpy(ptyibuf2ptr, ptyip, pcc+1); 1207 ptyip = ptyibuf2; 1208 pcc = strlen(ptyip); 1209 #ifdef LINEMODE 1210 /* 1211 * Last check to make sure all our states are correct. 1212 */ 1213 init_termbuf(); 1214 localstat(); 1215 #endif /* LINEMODE */ 1216 1217 DIAG(TD_REPORT, 1218 {output_data("td: Entering processing loop\r\n");}); 1219 1220 #ifdef convex 1221 startslave(host); 1222 #endif 1223 1224 nfd = ((f > p) ? f : p) + 1; 1225 for (;;) { 1226 fd_set ibits, obits, xbits; 1227 register int c; 1228 1229 if (ncc < 0 && pcc < 0) 1230 break; 1231 1232 FD_ZERO(&ibits); 1233 FD_ZERO(&obits); 1234 FD_ZERO(&xbits); 1235 1236 if (f >= FD_SETSIZE) 1237 fatal(net, "fd too large"); 1238 if (p >= FD_SETSIZE) 1239 fatal(net, "fd too large"); 1240 1241 /* 1242 * Never look for input if there's still 1243 * stuff in the corresponding output buffer 1244 */ 1245 if (nfrontp - nbackp || pcc > 0) { 1246 FD_SET(f, &obits); 1247 } else { 1248 FD_SET(p, &ibits); 1249 } 1250 if (pfrontp - pbackp || ncc > 0) { 1251 FD_SET(p, &obits); 1252 } else { 1253 FD_SET(f, &ibits); 1254 } 1255 if (!SYNCHing) { 1256 FD_SET(f, &xbits); 1257 } 1258 if ((c = select(nfd, &ibits, &obits, &xbits, 1259 (struct timeval *)0)) < 1) { 1260 if (c == -1) { 1261 if (errno == EINTR) { 1262 continue; 1263 } 1264 } 1265 sleep(5); 1266 continue; 1267 } 1268 1269 /* 1270 * Any urgent data? 1271 */ 1272 if (FD_ISSET(net, &xbits)) { 1273 SYNCHing = 1; 1274 } 1275 1276 /* 1277 * Something to read from the network... 1278 */ 1279 if (FD_ISSET(net, &ibits)) { 1280 #if !defined(SO_OOBINLINE) 1281 /* 1282 * In 4.2 (and 4.3 beta) systems, the 1283 * OOB indication and data handling in the kernel 1284 * is such that if two separate TCP Urgent requests 1285 * come in, one byte of TCP data will be overlaid. 1286 * This is fatal for Telnet, but we try to live 1287 * with it. 1288 * 1289 * In addition, in 4.2 (and...), a special protocol 1290 * is needed to pick up the TCP Urgent data in 1291 * the correct sequence. 1292 * 1293 * What we do is: if we think we are in urgent 1294 * mode, we look to see if we are "at the mark". 1295 * If we are, we do an OOB receive. If we run 1296 * this twice, we will do the OOB receive twice, 1297 * but the second will fail, since the second 1298 * time we were "at the mark", but there wasn't 1299 * any data there (the kernel doesn't reset 1300 * "at the mark" until we do a normal read). 1301 * Once we've read the OOB data, we go ahead 1302 * and do normal reads. 1303 * 1304 * There is also another problem, which is that 1305 * since the OOB byte we read doesn't put us 1306 * out of OOB state, and since that byte is most 1307 * likely the TELNET DM (data mark), we would 1308 * stay in the TELNET SYNCH (SYNCHing) state. 1309 * So, clocks to the rescue. If we've "just" 1310 * received a DM, then we test for the 1311 * presence of OOB data when the receive OOB 1312 * fails (and AFTER we did the normal mode read 1313 * to clear "at the mark"). 1314 */ 1315 if (SYNCHing) { 1316 int atmark; 1317 1318 (void) ioctl(net, SIOCATMARK, (char *)&atmark); 1319 if (atmark) { 1320 ncc = recv(net, netibuf, sizeof (netibuf), MSG_OOB); 1321 if ((ncc == -1) && (errno == EINVAL)) { 1322 ncc = read(net, netibuf, sizeof (netibuf)); 1323 if (sequenceIs(didnetreceive, gotDM)) { 1324 SYNCHing = stilloob(net); 1325 } 1326 } 1327 } else { 1328 ncc = read(net, netibuf, sizeof (netibuf)); 1329 } 1330 } else { 1331 ncc = read(net, netibuf, sizeof (netibuf)); 1332 } 1333 settimer(didnetreceive); 1334 #else /* !defined(SO_OOBINLINE)) */ 1335 ncc = read(net, netibuf, sizeof (netibuf)); 1336 #endif /* !defined(SO_OOBINLINE)) */ 1337 if (ncc < 0 && errno == EWOULDBLOCK) 1338 ncc = 0; 1339 else { 1340 if (ncc <= 0) { 1341 break; 1342 } 1343 netip = netibuf; 1344 } 1345 DIAG((TD_REPORT | TD_NETDATA), 1346 {output_data("td: netread %d chars\r\n", ncc);}); 1347 DIAG(TD_NETDATA, printdata("nd", netip, ncc)); 1348 } 1349 1350 /* 1351 * Something to read from the pty... 1352 */ 1353 if (FD_ISSET(p, &ibits)) { 1354 #ifndef STREAMSPTY 1355 pcc = read(p, ptyibuf, BUFSIZ); 1356 #else 1357 pcc = readstream(p, ptyibuf, BUFSIZ); 1358 #endif 1359 /* 1360 * On some systems, if we try to read something 1361 * off the master side before the slave side is 1362 * opened, we get EIO. 1363 */ 1364 if (pcc < 0 && (errno == EWOULDBLOCK || 1365 #ifdef EAGAIN 1366 errno == EAGAIN || 1367 #endif 1368 errno == EIO)) { 1369 pcc = 0; 1370 } else { 1371 if (pcc <= 0) 1372 break; 1373 #ifdef LINEMODE 1374 /* 1375 * If ioctl from pty, pass it through net 1376 */ 1377 if (ptyibuf[0] & TIOCPKT_IOCTL) { 1378 copy_termbuf(ptyibuf+1, pcc-1); 1379 localstat(); 1380 pcc = 1; 1381 } 1382 #endif /* LINEMODE */ 1383 if (ptyibuf[0] & TIOCPKT_FLUSHWRITE) { 1384 netclear(); /* clear buffer back */ 1385 #ifndef NO_URGENT 1386 /* 1387 * There are client telnets on some 1388 * operating systems get screwed up 1389 * royally if we send them urgent 1390 * mode data. 1391 */ 1392 output_data("%c%c", IAC, DM); 1393 neturg = nfrontp - 1; /* off by one XXX */ 1394 DIAG(TD_OPTIONS, 1395 printoption("td: send IAC", DM)); 1396 1397 #endif 1398 } 1399 if (his_state_is_will(TELOPT_LFLOW) && 1400 (ptyibuf[0] & 1401 (TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))) { 1402 int newflow = 1403 ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0; 1404 if (newflow != flowmode) { 1405 flowmode = newflow; 1406 (void) output_data( 1407 "%c%c%c%c%c%c", 1408 IAC, SB, TELOPT_LFLOW, 1409 flowmode ? LFLOW_ON 1410 : LFLOW_OFF, 1411 IAC, SE); 1412 DIAG(TD_OPTIONS, printsub('>', 1413 (unsigned char *)nfrontp - 4, 1414 4);); 1415 } 1416 } 1417 pcc--; 1418 ptyip = ptyibuf+1; 1419 } 1420 } 1421 1422 while (pcc > 0) { 1423 if ((&netobuf[BUFSIZ] - nfrontp) < 2) 1424 break; 1425 c = *ptyip++ & 0377, pcc--; 1426 if (c == IAC) 1427 output_data("%c", c); 1428 output_data("%c", c); 1429 if ((c == '\r') && (my_state_is_wont(TELOPT_BINARY))) { 1430 if (pcc > 0 && ((*ptyip & 0377) == '\n')) { 1431 output_data("%c", *ptyip++ & 0377); 1432 pcc--; 1433 } else 1434 output_datalen("\0", 1); 1435 } 1436 } 1437 1438 if (FD_ISSET(f, &obits) && (nfrontp - nbackp) > 0) 1439 netflush(); 1440 if (ncc > 0) 1441 telrcv(); 1442 if (FD_ISSET(p, &obits) && (pfrontp - pbackp) > 0) 1443 ptyflush(); 1444 } 1445 cleanup(0); 1446 } /* end of telnet */ 1447 1448 #ifndef TCSIG 1449 # ifdef TIOCSIG 1450 # define TCSIG TIOCSIG 1451 # endif 1452 #endif 1453 1454 #ifdef STREAMSPTY 1455 1456 int flowison = -1; /* current state of flow: -1 is unknown */ 1457 1458 int readstream(p, ibuf, bufsize) 1459 int p; 1460 char *ibuf; 1461 int bufsize; 1462 { 1463 int flags = 0; 1464 int ret = 0; 1465 struct termios *tsp; 1466 struct termio *tp; 1467 struct iocblk *ip; 1468 char vstop, vstart; 1469 int ixon; 1470 int newflow; 1471 1472 strbufc.maxlen = BUFSIZ; 1473 strbufc.buf = (char *)ctlbuf; 1474 strbufd.maxlen = bufsize-1; 1475 strbufd.len = 0; 1476 strbufd.buf = ibuf+1; 1477 ibuf[0] = 0; 1478 1479 ret = getmsg(p, &strbufc, &strbufd, &flags); 1480 if (ret < 0) /* error of some sort -- probably EAGAIN */ 1481 return(-1); 1482 1483 if (strbufc.len <= 0 || ctlbuf[0] == M_DATA) { 1484 /* data message */ 1485 if (strbufd.len > 0) { /* real data */ 1486 return(strbufd.len + 1); /* count header char */ 1487 } else { 1488 /* nothing there */ 1489 errno = EAGAIN; 1490 return(-1); 1491 } 1492 } 1493 1494 /* 1495 * It's a control message. Return 1, to look at the flag we set 1496 */ 1497 1498 switch (ctlbuf[0]) { 1499 case M_FLUSH: 1500 if (ibuf[1] & FLUSHW) 1501 ibuf[0] = TIOCPKT_FLUSHWRITE; 1502 return(1); 1503 1504 case M_IOCTL: 1505 ip = (struct iocblk *) (ibuf+1); 1506 1507 switch (ip->ioc_cmd) { 1508 case TCSETS: 1509 case TCSETSW: 1510 case TCSETSF: 1511 tsp = (struct termios *) 1512 (ibuf+1 + sizeof(struct iocblk)); 1513 vstop = tsp->c_cc[VSTOP]; 1514 vstart = tsp->c_cc[VSTART]; 1515 ixon = tsp->c_iflag & IXON; 1516 break; 1517 case TCSETA: 1518 case TCSETAW: 1519 case TCSETAF: 1520 tp = (struct termio *) (ibuf+1 + sizeof(struct iocblk)); 1521 vstop = tp->c_cc[VSTOP]; 1522 vstart = tp->c_cc[VSTART]; 1523 ixon = tp->c_iflag & IXON; 1524 break; 1525 default: 1526 errno = EAGAIN; 1527 return(-1); 1528 } 1529 1530 newflow = (ixon && (vstart == 021) && (vstop == 023)) ? 1 : 0; 1531 if (newflow != flowison) { /* it's a change */ 1532 flowison = newflow; 1533 ibuf[0] = newflow ? TIOCPKT_DOSTOP : TIOCPKT_NOSTOP; 1534 return(1); 1535 } 1536 } 1537 1538 /* nothing worth doing anything about */ 1539 errno = EAGAIN; 1540 return(-1); 1541 } 1542 #endif /* STREAMSPTY */ 1543 1544 /* 1545 * Send interrupt to process on other side of pty. 1546 * If it is in raw mode, just write NULL; 1547 * otherwise, write intr char. 1548 */ 1549 void 1550 interrupt() 1551 { 1552 ptyflush(); /* half-hearted */ 1553 1554 #if defined(STREAMSPTY) && defined(TIOCSIGNAL) 1555 /* Streams PTY style ioctl to post a signal */ 1556 { 1557 int sig = SIGINT; 1558 (void) ioctl(pty, TIOCSIGNAL, &sig); 1559 (void) ioctl(pty, I_FLUSH, FLUSHR); 1560 } 1561 #else 1562 #ifdef TCSIG 1563 (void) ioctl(pty, TCSIG, (char *)SIGINT); 1564 #else /* TCSIG */ 1565 init_termbuf(); 1566 *pfrontp++ = slctab[SLC_IP].sptr ? 1567 (unsigned char)*slctab[SLC_IP].sptr : '\177'; 1568 #endif /* TCSIG */ 1569 #endif 1570 } 1571 1572 /* 1573 * Send quit to process on other side of pty. 1574 * If it is in raw mode, just write NULL; 1575 * otherwise, write quit char. 1576 */ 1577 void 1578 sendbrk() 1579 { 1580 ptyflush(); /* half-hearted */ 1581 #ifdef TCSIG 1582 (void) ioctl(pty, TCSIG, (char *)SIGQUIT); 1583 #else /* TCSIG */ 1584 init_termbuf(); 1585 *pfrontp++ = slctab[SLC_ABORT].sptr ? 1586 (unsigned char)*slctab[SLC_ABORT].sptr : '\034'; 1587 #endif /* TCSIG */ 1588 } 1589 1590 void 1591 sendsusp() 1592 { 1593 #ifdef SIGTSTP 1594 ptyflush(); /* half-hearted */ 1595 # ifdef TCSIG 1596 (void) ioctl(pty, TCSIG, (char *)SIGTSTP); 1597 # else /* TCSIG */ 1598 *pfrontp++ = slctab[SLC_SUSP].sptr ? 1599 (unsigned char)*slctab[SLC_SUSP].sptr : '\032'; 1600 # endif /* TCSIG */ 1601 #endif /* SIGTSTP */ 1602 } 1603 1604 /* 1605 * When we get an AYT, if ^T is enabled, use that. Otherwise, 1606 * just send back "[Yes]". 1607 */ 1608 void 1609 recv_ayt() 1610 { 1611 #if defined(SIGINFO) && defined(TCSIG) 1612 if (slctab[SLC_AYT].sptr && *slctab[SLC_AYT].sptr != _POSIX_VDISABLE) { 1613 (void) ioctl(pty, TCSIG, (char *)SIGINFO); 1614 return; 1615 } 1616 #endif 1617 (void) output_data("\r\n[Yes]\r\n"); 1618 } 1619 1620 void 1621 doeof() 1622 { 1623 init_termbuf(); 1624 1625 #if defined(LINEMODE) && defined(USE_TERMIO) && (VEOF == VMIN) 1626 if (!tty_isediting()) { 1627 extern char oldeofc; 1628 *pfrontp++ = oldeofc; 1629 return; 1630 } 1631 #endif 1632 *pfrontp++ = slctab[SLC_EOF].sptr ? 1633 (unsigned char)*slctab[SLC_EOF].sptr : '\004'; 1634 } 1635