1 /* 2 * Copyright (c) 1989 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 char copyright[] = 10 "@(#) Copyright (c) 1989 Regents of the University of California.\n\ 11 All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)telnetd.c 5.48 (Berkeley) 03/01/91"; 16 #endif /* not lint */ 17 18 #include "telnetd.h" 19 #include "pathnames.h" 20 21 #if defined(AUTHENTICATE) 22 #include <libtelnet/auth.h> 23 int auth_level = 0; 24 #endif 25 #if defined(SecurID) 26 int require_SecurID = 0; 27 #endif 28 29 /* 30 * I/O data buffers, 31 * pointers, and counters. 32 */ 33 char ptyibuf[BUFSIZ], *ptyip = ptyibuf; 34 char ptyibuf2[BUFSIZ]; 35 36 int hostinfo = 1; /* do we print login banner? */ 37 38 #ifdef CRAY 39 extern int newmap; /* nonzero if \n maps to ^M^J */ 40 int lowpty = 0, highpty; /* low, high pty numbers */ 41 #endif /* CRAY */ 42 43 int debug = 0; 44 int keepalive = 1; 45 char *progname; 46 47 extern void usage P((void)); 48 49 main(argc, argv) 50 char *argv[]; 51 { 52 struct sockaddr_in from; 53 int on = 1, fromlen; 54 register int ch; 55 extern char *optarg; 56 extern int optind; 57 #if defined(IPPROTO_IP) && defined(IP_TOS) 58 int tos = -1; 59 #endif 60 61 pfrontp = pbackp = ptyobuf; 62 netip = netibuf; 63 nfrontp = nbackp = netobuf; 64 #if defined(ENCRYPT) 65 nclearto = 0; 66 #endif 67 68 progname = *argv; 69 70 #ifdef CRAY 71 /* 72 * Get number of pty's before trying to process options, 73 * which may include changing pty range. 74 */ 75 highpty = getnpty(); 76 #endif /* CRAY */ 77 78 while ((ch = getopt(argc, argv, "d:a:e:lhnr:I:D:B:sS:a:X:")) != EOF) { 79 switch(ch) { 80 81 #ifdef AUTHENTICATE 82 case 'a': 83 /* 84 * Check for required authentication level 85 */ 86 if (strcmp(optarg, "debug") == 0) { 87 extern int auth_debug_mode; 88 auth_debug_mode = 1; 89 } else if (strcasecmp(optarg, "none") == 0) { 90 auth_level = 0; 91 } else if (strcasecmp(optarg, "other") == 0) { 92 auth_level = AUTH_OTHER; 93 } else if (strcasecmp(optarg, "user") == 0) { 94 auth_level = AUTH_USER; 95 } else if (strcasecmp(optarg, "valid") == 0) { 96 auth_level = AUTH_VALID; 97 } else if (strcasecmp(optarg, "off") == 0) { 98 /* 99 * This hack turns off authentication 100 */ 101 auth_level = -1; 102 } else { 103 fprintf(stderr, 104 "telnetd: unknown authorization level for -a\n"); 105 } 106 break; 107 #endif /* AUTHENTICATE */ 108 109 #ifdef BFTPDAEMON 110 case 'B': 111 bftpd++; 112 break; 113 #endif /* BFTPDAEMON */ 114 115 case 'd': 116 if (strcmp(optarg, "ebug") == 0) { 117 debug++; 118 break; 119 } 120 usage(); 121 /* NOTREACHED */ 122 break; 123 124 #ifdef DIAGNOSTICS 125 case 'D': 126 /* 127 * Check for desired diagnostics capabilities. 128 */ 129 if (!strcmp(optarg, "report")) { 130 diagnostic |= TD_REPORT|TD_OPTIONS; 131 } else if (!strcmp(optarg, "exercise")) { 132 diagnostic |= TD_EXERCISE; 133 } else if (!strcmp(optarg, "netdata")) { 134 diagnostic |= TD_NETDATA; 135 } else if (!strcmp(optarg, "ptydata")) { 136 diagnostic |= TD_PTYDATA; 137 } else if (!strcmp(optarg, "options")) { 138 diagnostic |= TD_OPTIONS; 139 } else { 140 usage(); 141 /* NOT REACHED */ 142 } 143 break; 144 #endif /* DIAGNOSTICS */ 145 146 #ifdef AUTHENTICATE 147 case 'e': 148 if (strcmp(optarg, "debug") == 0) { 149 extern int encrypt_debug_mode; 150 encrypt_debug_mode = 1; 151 break; 152 } 153 usage(); 154 /* NOTREACHED */ 155 break; 156 #endif /* AUTHENTICATE */ 157 158 case 'h': 159 hostinfo = 0; 160 break; 161 162 #if defined(CRAY) && defined(NEWINIT) 163 case 'I': 164 { 165 extern char *gen_id; 166 gen_id = optarg; 167 break; 168 } 169 #endif /* defined(CRAY) && defined(NEWINIT) */ 170 171 #ifdef LINEMODE 172 case 'l': 173 alwayslinemode = 1; 174 break; 175 #endif /* LINEMODE */ 176 177 case 'n': 178 keepalive = 0; 179 break; 180 181 #ifdef CRAY 182 case 'r': 183 { 184 char *strchr(); 185 char *c; 186 187 /* 188 * Allow the specification of alterations 189 * to the pty search range. It is legal to 190 * specify only one, and not change the 191 * other from its default. 192 */ 193 c = strchr(optarg, '-'); 194 if (c) { 195 *c++ = '\0'; 196 highpty = atoi(c); 197 } 198 if (*optarg != '\0') 199 lowpty = atoi(optarg); 200 if ((lowpty > highpty) || (lowpty < 0) || 201 (highpty > 32767)) { 202 usage(); 203 /* NOT REACHED */ 204 } 205 break; 206 } 207 #endif /* CRAY */ 208 209 #ifdef SecurID 210 case 's': 211 /* SecurID required */ 212 require_SecurID = 1; 213 break; 214 #endif /* SecurID */ 215 case 'S': 216 #ifdef HAS_GETTOS 217 if ((tos = parsetos(optarg, "tcp")) < 0) 218 fprintf(stderr, "%s%s%s\n", 219 "telnetd: Bad TOS argument '", optarg, 220 "'; will try to use default TOS"); 221 #else 222 fprintf(stderr, "%s%s\n", "TOS option unavailable; ", 223 "-S flag not supported\n"); 224 #endif 225 break; 226 227 #ifdef AUTHENTICATE 228 case 'X': 229 /* 230 * Check for invalid authentication types 231 */ 232 auth_disable_name(optarg); 233 break; 234 #endif /* AUTHENTICATE */ 235 236 default: 237 fprintf(stderr, "telnetd: %s: unknown option\n", ch); 238 /* FALLTHROUGH */ 239 case '?': 240 usage(); 241 /* NOTREACHED */ 242 } 243 } 244 245 argc -= optind; 246 argv += optind; 247 248 if (debug) { 249 int s, ns, foo; 250 struct servent *sp; 251 static struct sockaddr_in sin = { AF_INET }; 252 253 if (argc > 1) { 254 usage(); 255 /* NOT REACHED */ 256 } else if (argc == 1) { 257 if (sp = getservbyname(*argv, "tcp")) { 258 sin.sin_port = sp->s_port; 259 } else { 260 sin.sin_port = atoi(*argv); 261 if ((int)sin.sin_port <= 0) { 262 fprintf(stderr, "telnetd: %s: bad port #\n", *argv); 263 usage(); 264 /* NOT REACHED */ 265 } 266 sin.sin_port = htons((u_short)sin.sin_port); 267 } 268 } else { 269 sp = getservbyname("telnet", "tcp"); 270 if (sp == 0) { 271 fprintf(stderr, "telnetd: tcp/telnet: unknown service\n"); 272 exit(1); 273 } 274 sin.sin_port = sp->s_port; 275 } 276 277 s = socket(AF_INET, SOCK_STREAM, 0); 278 if (s < 0) { 279 perror("telnetd: socket");; 280 exit(1); 281 } 282 (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 283 if (bind(s, (struct sockaddr *)&sin, sizeof sin) < 0) { 284 perror("bind"); 285 exit(1); 286 } 287 if (listen(s, 1) < 0) { 288 perror("listen"); 289 exit(1); 290 } 291 foo = sizeof sin; 292 ns = accept(s, (struct sockaddr *)&sin, &foo); 293 if (ns < 0) { 294 perror("accept"); 295 exit(1); 296 } 297 (void) dup2(ns, 0); 298 (void) close(ns); 299 (void) close(s); 300 #ifdef convex 301 } else if (argc == 1) { 302 ; /* VOID*/ /* Just ignore the host/port name */ 303 #endif 304 } else if (argc > 0) { 305 usage(); 306 /* NOT REACHED */ 307 } 308 309 openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON); 310 fromlen = sizeof (from); 311 if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { 312 fprintf(stderr, "%s: ", progname); 313 perror("getpeername"); 314 _exit(1); 315 } 316 if (keepalive && 317 setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) { 318 syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); 319 } 320 321 #if defined(IPPROTO_IP) && defined(IP_TOS) 322 { 323 # if defined(HAS_GETTOS) 324 struct tosent *tp; 325 if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) 326 tos = tp->t_tos; 327 # endif 328 if (tos < 0) 329 tos = 020; /* Low Delay bit */ 330 if (tos 331 && (setsockopt(0, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) 332 && (errno != ENOPROTOOPT) ) 333 syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); 334 } 335 #endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ 336 net = 0; 337 doit(&from); 338 /* NOTREACHED */ 339 } /* end of main */ 340 341 void 342 usage() 343 { 344 fprintf(stderr, "Usage: telnetd"); 345 #ifdef AUTHENTICATE 346 fprintf(stderr, " [-a (debug|other|user|valid|off)]\n\t"); 347 #endif 348 #ifdef BFTPDAEMON 349 fprintf(stderr, " [-B]"); 350 #endif 351 fprintf(stderr, " [-debug]"); 352 #ifdef DIAGNOSTICS 353 fprintf(stderr, " [-D (options|report|exercise|netdata|ptydata)]\n\t"); 354 #endif 355 #ifdef AUTHENTICATE 356 fprintf(stderr, " [-edebug]"); 357 #endif 358 fprintf(stderr, " [-h]"); 359 #if defined(CRAY) && defined(NEWINIT) 360 fprintf(stderr, " [-Iinitid]"); 361 #endif 362 #ifdef LINEMODE 363 fprintf(stderr, " [-l]"); 364 #endif 365 fprintf(stderr, " [-n]"); 366 #ifdef CRAY 367 fprintf(stderr, " [-r[lowpty]-[highpty]]"); 368 #endif 369 #ifdef SecurID 370 fprintf(stderr, " [-s]"); 371 #endif 372 #ifdef AUTHENTICATE 373 fprintf(stderr, " [-X auth-type]"); 374 #endif 375 fprintf(stderr, " [port]\n"); 376 exit(1); 377 } 378 379 /* 380 * getterminaltype 381 * 382 * Ask the other end to send along its terminal type and speed. 383 * Output is the variable terminaltype filled in. 384 */ 385 static char ttytype_sbbuf[] = { IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE }; 386 387 int 388 getterminaltype(name) 389 char *name; 390 { 391 int retval = -1; 392 void _gettermname(); 393 394 settimer(baseline); 395 #if defined(AUTHENTICATE) 396 /* 397 * Handle the Authentication option before we do anything else. 398 */ 399 send_do(TELOPT_AUTHENTICATION, 1); 400 while (his_will_wont_is_changing(TELOPT_AUTHENTICATION)) 401 ttloop(); 402 if (his_state_is_will(TELOPT_AUTHENTICATION)) { 403 retval = auth_wait(name); 404 } 405 #endif 406 407 #if defined(ENCRYPT) 408 send_will(TELOPT_ENCRYPT, 1); 409 #endif 410 send_do(TELOPT_TTYPE, 1); 411 send_do(TELOPT_TSPEED, 1); 412 send_do(TELOPT_XDISPLOC, 1); 413 send_do(TELOPT_ENVIRON, 1); 414 while ( 415 #if defined(ENCRYPT) 416 his_do_dont_is_changing(TELOPT_ENCRYPT) || 417 #endif 418 his_will_wont_is_changing(TELOPT_TTYPE) || 419 his_will_wont_is_changing(TELOPT_TSPEED) || 420 his_will_wont_is_changing(TELOPT_XDISPLOC) || 421 his_will_wont_is_changing(TELOPT_ENVIRON)) { 422 ttloop(); 423 } 424 #if defined(ENCRYPT) 425 /* 426 * Wait for the negotiation of what type of encryption we can 427 * send with. If autoencrypt is not set, this will just return. 428 */ 429 if (his_state_is_will(TELOPT_ENCRYPT)) { 430 encrypt_wait(); 431 } 432 #endif 433 if (his_state_is_will(TELOPT_TSPEED)) { 434 static char sbbuf[] = { IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE }; 435 436 bcopy(sbbuf, nfrontp, sizeof sbbuf); 437 nfrontp += sizeof sbbuf; 438 } 439 if (his_state_is_will(TELOPT_XDISPLOC)) { 440 static char sbbuf[] = { IAC, SB, TELOPT_XDISPLOC, TELQUAL_SEND, IAC, SE }; 441 442 bcopy(sbbuf, nfrontp, sizeof sbbuf); 443 nfrontp += sizeof sbbuf; 444 } 445 if (his_state_is_will(TELOPT_ENVIRON)) { 446 static char sbbuf[] = { IAC, SB, TELOPT_ENVIRON, TELQUAL_SEND, IAC, SE }; 447 448 bcopy(sbbuf, nfrontp, sizeof sbbuf); 449 nfrontp += sizeof sbbuf; 450 } 451 if (his_state_is_will(TELOPT_TTYPE)) { 452 453 bcopy(ttytype_sbbuf, nfrontp, sizeof ttytype_sbbuf); 454 nfrontp += sizeof ttytype_sbbuf; 455 } 456 if (his_state_is_will(TELOPT_TSPEED)) { 457 while (sequenceIs(tspeedsubopt, baseline)) 458 ttloop(); 459 } 460 if (his_state_is_will(TELOPT_XDISPLOC)) { 461 while (sequenceIs(xdisplocsubopt, baseline)) 462 ttloop(); 463 } 464 if (his_state_is_will(TELOPT_ENVIRON)) { 465 while (sequenceIs(environsubopt, baseline)) 466 ttloop(); 467 } 468 if (his_state_is_will(TELOPT_TTYPE)) { 469 char first[256], last[256]; 470 471 while (sequenceIs(ttypesubopt, baseline)) 472 ttloop(); 473 474 /* 475 * If the other side has already disabled the option, then 476 * we have to just go with what we (might) have already gotten. 477 */ 478 if (his_state_is_will(TELOPT_TTYPE) && !terminaltypeok(terminaltype)) { 479 (void) strncpy(first, terminaltype, sizeof(first)); 480 for(;;) { 481 /* 482 * Save the unknown name, and request the next name. 483 */ 484 (void) strncpy(last, terminaltype, sizeof(last)); 485 _gettermname(); 486 if (terminaltypeok(terminaltype)) 487 break; 488 if ((strncmp(last, terminaltype, sizeof(last)) == 0) || 489 his_state_is_wont(TELOPT_TTYPE)) { 490 /* 491 * We've hit the end. If this is the same as 492 * the first name, just go with it. 493 */ 494 if (strncmp(first, terminaltype, sizeof(first)) == 0) 495 break; 496 /* 497 * Get the terminal name one more time, so that 498 * RFC1091 compliant telnets will cycle back to 499 * the start of the list. 500 */ 501 _gettermname(); 502 if (strncmp(first, terminaltype, sizeof(first)) != 0) 503 (void) strncpy(terminaltype, first, sizeof(first)); 504 break; 505 } 506 } 507 } 508 } 509 return(retval); 510 } /* end of getterminaltype */ 511 512 void 513 _gettermname() 514 { 515 /* 516 * If the client turned off the option, 517 * we can't send another request, so we 518 * just return. 519 */ 520 if (his_state_is_wont(TELOPT_TTYPE)) 521 return; 522 settimer(baseline); 523 bcopy(ttytype_sbbuf, nfrontp, sizeof ttytype_sbbuf); 524 nfrontp += sizeof ttytype_sbbuf; 525 while (sequenceIs(ttypesubopt, baseline)) 526 ttloop(); 527 } 528 529 int 530 terminaltypeok(s) 531 char *s; 532 { 533 char buf[1024]; 534 535 if (terminaltype == NULL) 536 return(1); 537 538 /* 539 * tgetent() will return 1 if the type is known, and 540 * 0 if it is not known. If it returns -1, it couldn't 541 * open the database. But if we can't open the database, 542 * it won't help to say we failed, because we won't be 543 * able to verify anything else. So, we treat -1 like 1. 544 */ 545 if (tgetent(buf, s) == 0) 546 return(0); 547 return(1); 548 } 549 550 #ifndef MAXHOSTNAMELEN 551 #define MAXHOSTNAMELEN 64 552 #endif /* MAXHOSTNAMELEN */ 553 554 char *hostname; 555 char host_name[MAXHOSTNAMELEN]; 556 char remote_host_name[MAXHOSTNAMELEN]; 557 558 #ifndef convex 559 extern void telnet P((int, int)); 560 #else 561 extern void telnet P((int, int, char *)); 562 #endif 563 564 /* 565 * Get a pty, scan input lines. 566 */ 567 doit(who) 568 struct sockaddr_in *who; 569 { 570 char *host, *inet_ntoa(); 571 int t; 572 struct hostent *hp; 573 int level; 574 char user_name[256]; 575 576 /* 577 * Find an available pty to use. 578 */ 579 #ifndef convex 580 pty = getpty(); 581 if (pty < 0) 582 fatal(net, "All network ports in use"); 583 #else 584 for (;;) { 585 char *lp; 586 extern char *line, *getpty(); 587 588 if ((lp = getpty()) == NULL) 589 fatal(net, "Out of ptys"); 590 591 if ((pty = open(lp, 2)) >= 0) { 592 strcpy(line,lp); 593 line[5] = 't'; 594 break; 595 } 596 } 597 #endif 598 599 /* get name of connected client */ 600 hp = gethostbyaddr((char *)&who->sin_addr, sizeof (struct in_addr), 601 who->sin_family); 602 if (hp) 603 host = hp->h_name; 604 else 605 host = inet_ntoa(who->sin_addr); 606 /* 607 * We must make a copy because Kerberos is probably going 608 * to also do a gethost* and overwrite the static data... 609 */ 610 strncpy(remote_host_name, host, sizeof(remote_host_name)-1); 611 remote_host_name[sizeof(remote_host_name)-1] = 0; 612 host = remote_host_name; 613 614 (void) gethostname(host_name, sizeof (host_name)); 615 hostname = host_name; 616 617 #if defined(AUTHENTICATE) || defined(ENCRYPT) 618 auth_encrypt_init(hostname, host, "TELNETD", 1); 619 #endif 620 621 init_env(); 622 /* 623 * get terminal type. 624 */ 625 *user_name = 0; 626 level = getterminaltype(user_name); 627 setenv("TERM", terminaltype ? terminaltype : "network", 1); 628 629 /* 630 * Start up the login process on the slave side of the terminal 631 */ 632 #ifndef convex 633 startslave(host, level, user_name); 634 635 telnet(net, pty); /* begin server processing */ 636 #else 637 telnet(net, pty, host); 638 #endif 639 /*NOTREACHED*/ 640 } /* end of doit */ 641 642 #if defined(CRAY2) && defined(UNICOS5) && defined(UNICOS50) 643 int 644 Xterm_output(ibufp, obuf, icountp, ocount) 645 char **ibufp, *obuf; 646 int *icountp, ocount; 647 { 648 int ret; 649 ret = term_output(*ibufp, obuf, *icountp, ocount); 650 *ibufp += *icountp; 651 *icountp = 0; 652 return(ret); 653 } 654 #define term_output Xterm_output 655 #endif /* defined(CRAY2) && defined(UNICOS5) && defined(UNICOS50) */ 656 657 /* 658 * Main loop. Select from pty and network, and 659 * hand data to telnet receiver finite state machine. 660 */ 661 void 662 #ifndef convex 663 telnet(f, p) 664 #else 665 telnet(f, p, host) 666 #endif 667 int f, p; 668 #ifdef convex 669 char *host; 670 #endif 671 { 672 int on = 1; 673 #define TABBUFSIZ 512 674 char defent[TABBUFSIZ]; 675 char defstrs[TABBUFSIZ]; 676 #undef TABBUFSIZ 677 char *HE; 678 char *HN; 679 char *IM; 680 void netflush(); 681 682 /* 683 * Initialize the slc mapping table. 684 */ 685 get_slc_defaults(); 686 687 /* 688 * Do some tests where it is desireable to wait for a response. 689 * Rather than doing them slowly, one at a time, do them all 690 * at once. 691 */ 692 if (my_state_is_wont(TELOPT_SGA)) 693 send_will(TELOPT_SGA, 1); 694 /* 695 * Is the client side a 4.2 (NOT 4.3) system? We need to know this 696 * because 4.2 clients are unable to deal with TCP urgent data. 697 * 698 * To find out, we send out a "DO ECHO". If the remote system 699 * answers "WILL ECHO" it is probably a 4.2 client, and we note 700 * that fact ("WILL ECHO" ==> that the client will echo what 701 * WE, the server, sends it; it does NOT mean that the client will 702 * echo the terminal input). 703 */ 704 send_do(TELOPT_ECHO, 1); 705 706 #ifdef LINEMODE 707 if (his_state_is_wont(TELOPT_LINEMODE)) { 708 /* Query the peer for linemode support by trying to negotiate 709 * the linemode option. 710 */ 711 linemode = 0; 712 editmode = 0; 713 send_do(TELOPT_LINEMODE, 1); /* send do linemode */ 714 } 715 #endif /* LINEMODE */ 716 717 /* 718 * Send along a couple of other options that we wish to negotiate. 719 */ 720 send_do(TELOPT_NAWS, 1); 721 send_will(TELOPT_STATUS, 1); 722 flowmode = 1; /* default flow control state */ 723 send_do(TELOPT_LFLOW, 1); 724 725 /* 726 * Spin, waiting for a response from the DO ECHO. However, 727 * some REALLY DUMB telnets out there might not respond 728 * to the DO ECHO. So, we spin looking for NAWS, (most dumb 729 * telnets so far seem to respond with WONT for a DO that 730 * they don't understand...) because by the time we get the 731 * response, it will already have processed the DO ECHO. 732 * Kludge upon kludge. 733 */ 734 while (his_will_wont_is_changing(TELOPT_NAWS)) 735 ttloop(); 736 737 /* 738 * But... 739 * The client might have sent a WILL NAWS as part of its 740 * startup code; if so, we'll be here before we get the 741 * response to the DO ECHO. We'll make the assumption 742 * that any implementation that understands about NAWS 743 * is a modern enough implementation that it will respond 744 * to our DO ECHO request; hence we'll do another spin 745 * waiting for the ECHO option to settle down, which is 746 * what we wanted to do in the first place... 747 */ 748 if (his_want_state_is_will(TELOPT_ECHO) && 749 his_state_is_will(TELOPT_NAWS)) { 750 while (his_will_wont_is_changing(TELOPT_ECHO)) 751 ttloop(); 752 } 753 /* 754 * On the off chance that the telnet client is broken and does not 755 * respond to the DO ECHO we sent, (after all, we did send the 756 * DO NAWS negotiation after the DO ECHO, and we won't get here 757 * until a response to the DO NAWS comes back) simulate the 758 * receipt of a will echo. This will also send a WONT ECHO 759 * to the client, since we assume that the client failed to 760 * respond because it believes that it is already in DO ECHO 761 * mode, which we do not want. 762 */ 763 if (his_want_state_is_will(TELOPT_ECHO)) { 764 DIAG(TD_OPTIONS, 765 {sprintf(nfrontp, "td: simulating recv\r\n"); 766 nfrontp += strlen(nfrontp);}); 767 willoption(TELOPT_ECHO); 768 } 769 770 /* 771 * Finally, to clean things up, we turn on our echo. This 772 * will break stupid 4.2 telnets out of local terminal echo. 773 */ 774 775 if (my_state_is_wont(TELOPT_ECHO)) 776 send_will(TELOPT_ECHO, 1); 777 778 /* 779 * Turn on packet mode 780 */ 781 (void) ioctl(p, TIOCPKT, (char *)&on); 782 #if defined(LINEMODE) && defined(KLUDGELINEMODE) 783 /* 784 * Continuing line mode support. If client does not support 785 * real linemode, attempt to negotiate kludge linemode by sending 786 * the do timing mark sequence. 787 */ 788 if (lmodetype < REAL_LINEMODE) 789 send_do(TELOPT_TM, 1); 790 #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ 791 792 /* 793 * Call telrcv() once to pick up anything received during 794 * terminal type negotiation, 4.2/4.3 determination, and 795 * linemode negotiation. 796 */ 797 telrcv(); 798 799 (void) ioctl(f, FIONBIO, (char *)&on); 800 (void) ioctl(p, FIONBIO, (char *)&on); 801 #if defined(CRAY2) && defined(UNICOS5) 802 init_termdriver(f, p, interrupt, sendbrk); 803 #endif 804 805 #if defined(SO_OOBINLINE) 806 (void) setsockopt(net, SOL_SOCKET, SO_OOBINLINE, &on, sizeof on); 807 #endif /* defined(SO_OOBINLINE) */ 808 809 #ifdef SIGTSTP 810 (void) signal(SIGTSTP, SIG_IGN); 811 #endif 812 #ifdef SIGTTOU 813 /* 814 * Ignoring SIGTTOU keeps the kernel from blocking us 815 * in ttioct() in /sys/tty.c. 816 */ 817 (void) signal(SIGTTOU, SIG_IGN); 818 #endif 819 820 (void) signal(SIGCHLD, cleanup); 821 822 #if defined(CRAY2) && defined(UNICOS5) 823 /* 824 * Cray-2 will send a signal when pty modes are changed by slave 825 * side. Set up signal handler now. 826 */ 827 if ((int)signal(SIGUSR1, termstat) < 0) 828 perror("signal"); 829 else if (ioctl(p, TCSIGME, (char *)SIGUSR1) < 0) 830 perror("ioctl:TCSIGME"); 831 /* 832 * Make processing loop check terminal characteristics early on. 833 */ 834 termstat(); 835 #endif 836 837 #ifdef TIOCNOTTY 838 { 839 register int t; 840 t = open(_PATH_TTY, O_RDWR); 841 if (t >= 0) { 842 (void) ioctl(t, TIOCNOTTY, (char *)0); 843 (void) close(t); 844 } 845 } 846 #endif 847 848 #if defined(CRAY) && defined(NEWINIT) && defined(TIOCSCTTY) 849 (void) setsid(); 850 ioctl(p, TIOCSCTTY, 0); 851 #endif 852 853 /* 854 * Show banner that getty never gave. 855 * 856 * We put the banner in the pty input buffer. This way, it 857 * gets carriage return null processing, etc., just like all 858 * other pty --> client data. 859 */ 860 861 #if !defined(CRAY) || !defined(NEWINIT) 862 if (getenv("USER")) 863 hostinfo = 0; 864 #endif 865 866 if (getent(defent, "default") == 1) { 867 char *getstr(); 868 char *cp=defstrs; 869 870 HE = getstr("he", &cp); 871 HN = getstr("hn", &cp); 872 IM = getstr("im", &cp); 873 if (HN && *HN) 874 (void) strcpy(host_name, HN); 875 if (IM == 0) 876 IM = ""; 877 } else { 878 IM = DEFAULT_IM; 879 HE = 0; 880 } 881 edithost(HE, host_name); 882 if (hostinfo && *IM) 883 putf(IM, ptyibuf2); 884 885 if (pcc) 886 (void) strncat(ptyibuf2, ptyip, pcc+1); 887 ptyip = ptyibuf2; 888 pcc = strlen(ptyip); 889 #ifdef LINEMODE 890 /* 891 * Last check to make sure all our states are correct. 892 */ 893 init_termbuf(); 894 localstat(); 895 #endif /* LINEMODE */ 896 897 DIAG(TD_REPORT, 898 {sprintf(nfrontp, "td: Entering processing loop\r\n"); 899 nfrontp += strlen(nfrontp);}); 900 901 #ifdef convex 902 startslave(host); 903 #endif 904 905 for (;;) { 906 fd_set ibits, obits, xbits; 907 register int c; 908 909 if (ncc < 0 && pcc < 0) 910 break; 911 912 #if defined(CRAY2) && defined(UNICOS5) 913 if (needtermstat) 914 _termstat(); 915 #endif /* defined(CRAY2) && defined(UNICOS5) */ 916 FD_ZERO(&ibits); 917 FD_ZERO(&obits); 918 FD_ZERO(&xbits); 919 /* 920 * Never look for input if there's still 921 * stuff in the corresponding output buffer 922 */ 923 if (nfrontp - nbackp || pcc > 0) { 924 FD_SET(f, &obits); 925 } else { 926 FD_SET(p, &ibits); 927 } 928 if (pfrontp - pbackp || ncc > 0) { 929 FD_SET(p, &obits); 930 } else { 931 FD_SET(f, &ibits); 932 } 933 if (!SYNCHing) { 934 FD_SET(f, &xbits); 935 } 936 if ((c = select(16, &ibits, &obits, &xbits, 937 (struct timeval *)0)) < 1) { 938 if (c == -1) { 939 if (errno == EINTR) { 940 continue; 941 } 942 } 943 sleep(5); 944 continue; 945 } 946 947 /* 948 * Any urgent data? 949 */ 950 if (FD_ISSET(net, &xbits)) { 951 SYNCHing = 1; 952 } 953 954 /* 955 * Something to read from the network... 956 */ 957 if (FD_ISSET(net, &ibits)) { 958 #if !defined(SO_OOBINLINE) 959 /* 960 * In 4.2 (and 4.3 beta) systems, the 961 * OOB indication and data handling in the kernel 962 * is such that if two separate TCP Urgent requests 963 * come in, one byte of TCP data will be overlaid. 964 * This is fatal for Telnet, but we try to live 965 * with it. 966 * 967 * In addition, in 4.2 (and...), a special protocol 968 * is needed to pick up the TCP Urgent data in 969 * the correct sequence. 970 * 971 * What we do is: if we think we are in urgent 972 * mode, we look to see if we are "at the mark". 973 * If we are, we do an OOB receive. If we run 974 * this twice, we will do the OOB receive twice, 975 * but the second will fail, since the second 976 * time we were "at the mark", but there wasn't 977 * any data there (the kernel doesn't reset 978 * "at the mark" until we do a normal read). 979 * Once we've read the OOB data, we go ahead 980 * and do normal reads. 981 * 982 * There is also another problem, which is that 983 * since the OOB byte we read doesn't put us 984 * out of OOB state, and since that byte is most 985 * likely the TELNET DM (data mark), we would 986 * stay in the TELNET SYNCH (SYNCHing) state. 987 * So, clocks to the rescue. If we've "just" 988 * received a DM, then we test for the 989 * presence of OOB data when the receive OOB 990 * fails (and AFTER we did the normal mode read 991 * to clear "at the mark"). 992 */ 993 if (SYNCHing) { 994 int atmark; 995 996 (void) ioctl(net, SIOCATMARK, (char *)&atmark); 997 if (atmark) { 998 ncc = recv(net, netibuf, sizeof (netibuf), MSG_OOB); 999 if ((ncc == -1) && (errno == EINVAL)) { 1000 ncc = read(net, netibuf, sizeof (netibuf)); 1001 if (sequenceIs(didnetreceive, gotDM)) { 1002 SYNCHing = stilloob(net); 1003 } 1004 } 1005 } else { 1006 ncc = read(net, netibuf, sizeof (netibuf)); 1007 } 1008 } else { 1009 ncc = read(net, netibuf, sizeof (netibuf)); 1010 } 1011 settimer(didnetreceive); 1012 #else /* !defined(SO_OOBINLINE)) */ 1013 ncc = read(net, netibuf, sizeof (netibuf)); 1014 #endif /* !defined(SO_OOBINLINE)) */ 1015 if (ncc < 0 && errno == EWOULDBLOCK) 1016 ncc = 0; 1017 else { 1018 if (ncc <= 0) { 1019 break; 1020 } 1021 netip = netibuf; 1022 } 1023 DIAG((TD_REPORT | TD_NETDATA), 1024 {sprintf(nfrontp, "td: netread %d chars\r\n", ncc); 1025 nfrontp += strlen(nfrontp);}); 1026 DIAG(TD_NETDATA, printdata("nd", netip, ncc)); 1027 } 1028 1029 /* 1030 * Something to read from the pty... 1031 */ 1032 if (FD_ISSET(p, &ibits)) { 1033 pcc = read(p, ptyibuf, BUFSIZ); 1034 /* 1035 * On some systems, if we try to read something 1036 * off the master side before the slave side is 1037 * opened, we get EIO. 1038 */ 1039 if (pcc < 0 && (errno == EWOULDBLOCK || errno == EIO)) { 1040 pcc = 0; 1041 } else { 1042 if (pcc <= 0) 1043 break; 1044 #if !defined(CRAY2) || !defined(UNICOS5) 1045 #ifdef LINEMODE 1046 /* 1047 * If ioctl from pty, pass it through net 1048 */ 1049 if (ptyibuf[0] & TIOCPKT_IOCTL) { 1050 copy_termbuf(ptyibuf+1, pcc-1); 1051 localstat(); 1052 pcc = 1; 1053 } 1054 #endif /* LINEMODE */ 1055 if (ptyibuf[0] & TIOCPKT_FLUSHWRITE) { 1056 netclear(); /* clear buffer back */ 1057 #ifndef NO_URGENT 1058 /* 1059 * There are client telnets on some 1060 * operating systems get screwed up 1061 * royally if we send them urgent 1062 * mode data. 1063 */ 1064 *nfrontp++ = IAC; 1065 *nfrontp++ = DM; 1066 neturg = nfrontp-1; /* off by one XXX */ 1067 #endif 1068 } 1069 if (his_state_is_will(TELOPT_LFLOW) && 1070 (ptyibuf[0] & 1071 (TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))) { 1072 (void) sprintf(nfrontp, "%c%c%c%c%c%c", 1073 IAC, SB, TELOPT_LFLOW, 1074 ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0, 1075 IAC, SE); 1076 nfrontp += 6; 1077 } 1078 pcc--; 1079 ptyip = ptyibuf+1; 1080 #else /* defined(CRAY2) && defined(UNICOS5) */ 1081 if (!uselinemode) { 1082 unpcc = pcc; 1083 unptyip = ptyibuf; 1084 pcc = term_output(&unptyip, ptyibuf2, 1085 &unpcc, BUFSIZ); 1086 ptyip = ptyibuf2; 1087 } else 1088 ptyip = ptyibuf; 1089 #endif /* defined(CRAY2) && defined(UNICOS5) */ 1090 } 1091 } 1092 1093 while (pcc > 0) { 1094 if ((&netobuf[BUFSIZ] - nfrontp) < 2) 1095 break; 1096 c = *ptyip++ & 0377, pcc--; 1097 if (c == IAC) 1098 *nfrontp++ = c; 1099 #if defined(CRAY2) && defined(UNICOS5) 1100 else if (c == '\n' && 1101 my_state_is_wont(TELOPT_BINARY) && newmap) 1102 *nfrontp++ = '\r'; 1103 #endif /* defined(CRAY2) && defined(UNICOS5) */ 1104 *nfrontp++ = c; 1105 if ((c == '\r') && (my_state_is_wont(TELOPT_BINARY))) { 1106 if (pcc > 0 && ((*ptyip & 0377) == '\n')) { 1107 *nfrontp++ = *ptyip++ & 0377; 1108 pcc--; 1109 } else 1110 *nfrontp++ = '\0'; 1111 } 1112 } 1113 #if defined(CRAY2) && defined(UNICOS5) 1114 /* 1115 * If chars were left over from the terminal driver, 1116 * note their existence. 1117 */ 1118 if (!uselinemode && unpcc) { 1119 pcc = unpcc; 1120 unpcc = 0; 1121 ptyip = unptyip; 1122 } 1123 #endif /* defined(CRAY2) && defined(UNICOS5) */ 1124 1125 if (FD_ISSET(f, &obits) && (nfrontp - nbackp) > 0) 1126 netflush(); 1127 if (ncc > 0) 1128 telrcv(); 1129 if (FD_ISSET(p, &obits) && (pfrontp - pbackp) > 0) 1130 ptyflush(); 1131 } 1132 cleanup(0); 1133 } /* end of telnet */ 1134 1135 #ifndef TCSIG 1136 # ifdef TIOCSIG 1137 # define TCSIG TIOCSIG 1138 # endif 1139 #endif 1140 1141 /* 1142 * Send interrupt to process on other side of pty. 1143 * If it is in raw mode, just write NULL; 1144 * otherwise, write intr char. 1145 */ 1146 void 1147 interrupt() 1148 { 1149 ptyflush(); /* half-hearted */ 1150 1151 #ifdef TCSIG 1152 (void) ioctl(pty, TCSIG, (char *)SIGINT); 1153 #else /* TCSIG */ 1154 init_termbuf(); 1155 *pfrontp++ = slctab[SLC_IP].sptr ? 1156 (unsigned char)*slctab[SLC_IP].sptr : '\177'; 1157 #endif /* TCSIG */ 1158 } 1159 1160 /* 1161 * Send quit to process on other side of pty. 1162 * If it is in raw mode, just write NULL; 1163 * otherwise, write quit char. 1164 */ 1165 void 1166 sendbrk() 1167 { 1168 ptyflush(); /* half-hearted */ 1169 #ifdef TCSIG 1170 (void) ioctl(pty, TCSIG, (char *)SIGQUIT); 1171 #else /* TCSIG */ 1172 init_termbuf(); 1173 *pfrontp++ = slctab[SLC_ABORT].sptr ? 1174 (unsigned char)*slctab[SLC_ABORT].sptr : '\034'; 1175 #endif /* TCSIG */ 1176 } 1177 1178 void 1179 sendsusp() 1180 { 1181 #ifdef SIGTSTP 1182 ptyflush(); /* half-hearted */ 1183 # ifdef TCSIG 1184 (void) ioctl(pty, TCSIG, (char *)SIGTSTP); 1185 # else /* TCSIG */ 1186 *pfrontp++ = slctab[SLC_SUSP].sptr ? 1187 (unsigned char)*slctab[SLC_SUSP].sptr : '\032'; 1188 # endif /* TCSIG */ 1189 #endif /* SIGTSTP */ 1190 } 1191 1192 /* 1193 * When we get an AYT, if ^T is enabled, use that. Otherwise, 1194 * just send back "[Yes]". 1195 */ 1196 void 1197 recv_ayt() 1198 { 1199 #if defined(SIGINFO) && defined(TCSIG) 1200 if (slctab[SLC_AYT].sptr && *slctab[SLC_AYT].sptr != _POSIX_VDISABLE) { 1201 (void) ioctl(pty, TCSIG, (char *)SIGINFO); 1202 return; 1203 } 1204 #endif 1205 (void) strcpy(nfrontp, "\r\n[Yes]\r\n"); 1206 nfrontp += 9; 1207 } 1208 1209 void 1210 doeof() 1211 { 1212 init_termbuf(); 1213 1214 #if defined(LINEMODE) && defined(USE_TERMIO) && (VEOF == VMIN) 1215 if (!tty_isediting()) { 1216 extern char oldeofc; 1217 *pfrontp++ = oldeofc; 1218 return; 1219 } 1220 #endif 1221 *pfrontp++ = slctab[SLC_EOF].sptr ? 1222 (unsigned char)*slctab[SLC_EOF].sptr : '\004'; 1223 } 1224