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