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