1 /* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)telnetd.c 8.4 (Berkeley) 5/30/95 34 * $FreeBSD: src/libexec/telnetd/telnetd.c,v 1.22.2.8 2002/04/13 11:07:12 markm Exp $ 35 * $DragonFly: src/libexec/telnetd/telnetd.c,v 1.3 2006/01/12 13:43:10 corecode Exp $ 36 */ 37 38 #include "telnetd.h" 39 #include "pathnames.h" 40 41 #include <sys/mman.h> 42 #include <err.h> 43 #include <libutil.h> 44 #include <paths.h> 45 #include <termcap.h> 46 #include <utmp.h> 47 48 #include <arpa/inet.h> 49 50 #include <libtelnet/misc.h> 51 52 char remote_hostname[MAXHOSTNAMELEN]; 53 size_t utmp_len = sizeof(remote_hostname) - 1; 54 int registerd_host_only = 0; 55 56 57 /* 58 * I/O data buffers, 59 * pointers, and counters. 60 */ 61 char ptyibuf[BUFSIZ], *ptyip = ptyibuf; 62 char ptyibuf2[BUFSIZ]; 63 64 int readstream(int, char *, int); 65 void doit(struct sockaddr *); 66 int terminaltypeok(char *); 67 68 int hostinfo = 1; /* do we print login banner? */ 69 70 int debug = 0; 71 int keepalive = 1; 72 const char *altlogin; 73 74 void doit(struct sockaddr *); 75 int terminaltypeok(char *); 76 void startslave(char *, int, char *); 77 extern void usage(void); 78 static void _gettermname(void); 79 80 /* 81 * The string to pass to getopt(). We do it this way so 82 * that only the actual options that we support will be 83 * passed off to getopt(). 84 */ 85 char valid_opts[] = { 86 'd', ':', 'h', 'k', 'n', 'p', ':', 'S', ':', 'u', ':', 'U', 87 '4', '6', 88 #ifdef BFTPDAEMON 89 'B', 90 #endif 91 #ifdef DIAGNOSTICS 92 'D', ':', 93 #endif 94 #ifdef LINEMODE 95 'l', 96 #endif 97 '\0' 98 }; 99 100 int family = AF_INET; 101 102 #ifndef MAXHOSTNAMELEN 103 #define MAXHOSTNAMELEN 256 104 #endif /* MAXHOSTNAMELEN */ 105 106 char *hostname; 107 char host_name[MAXHOSTNAMELEN]; 108 109 extern void telnet(int, int, char *); 110 111 int level; 112 char user_name[256]; 113 114 int 115 main(int argc, char *argv[]) 116 { 117 struct sockaddr_storage from; 118 int on = 1, fromlen; 119 int ch; 120 #if defined(IPPROTO_IP) && defined(IP_TOS) 121 int tos = -1; 122 #endif 123 124 pfrontp = pbackp = ptyobuf; 125 netip = netibuf; 126 nfrontp = nbackp = netobuf; 127 128 /* 129 * This initialization causes linemode to default to a configuration 130 * that works on all telnet clients, including the FreeBSD client. 131 * This is not quite the same as the telnet client issuing a "mode 132 * character" command, but has most of the same benefits, and is 133 * preferable since some clients (like usofts) don't have the 134 * mode character command anyway and linemode breaks things. 135 * The most notable symptom of fix is that csh "set filec" operations 136 * like <ESC> (filename completion) and ^D (choices) keys now work 137 * in telnet sessions and can be used more than once on the same line. 138 * CR/LF handling is also corrected in some termio modes. This 139 * change resolves problem reports bin/771 and bin/1037. 140 */ 141 142 linemode=1; /*Default to mode that works on bulk of clients*/ 143 144 while ((ch = getopt(argc, argv, valid_opts)) != -1) { 145 switch(ch) { 146 147 148 #ifdef BFTPDAEMON 149 case 'B': 150 bftpd++; 151 break; 152 #endif /* BFTPDAEMON */ 153 154 case 'd': 155 if (strcmp(optarg, "ebug") == 0) { 156 debug++; 157 break; 158 } 159 usage(); 160 /* NOTREACHED */ 161 break; 162 163 #ifdef DIAGNOSTICS 164 case 'D': 165 /* 166 * Check for desired diagnostics capabilities. 167 */ 168 if (!strcmp(optarg, "report")) { 169 diagnostic |= TD_REPORT|TD_OPTIONS; 170 } else if (!strcmp(optarg, "exercise")) { 171 diagnostic |= TD_EXERCISE; 172 } else if (!strcmp(optarg, "netdata")) { 173 diagnostic |= TD_NETDATA; 174 } else if (!strcmp(optarg, "ptydata")) { 175 diagnostic |= TD_PTYDATA; 176 } else if (!strcmp(optarg, "options")) { 177 diagnostic |= TD_OPTIONS; 178 } else { 179 usage(); 180 /* NOT REACHED */ 181 } 182 break; 183 #endif /* DIAGNOSTICS */ 184 185 186 case 'h': 187 hostinfo = 0; 188 break; 189 190 #ifdef LINEMODE 191 case 'l': 192 alwayslinemode = 1; 193 break; 194 #endif /* LINEMODE */ 195 196 case 'k': 197 #if defined(LINEMODE) && defined(KLUDGELINEMODE) 198 lmodetype = NO_AUTOKLUDGE; 199 #else 200 /* ignore -k option if built without kludge linemode */ 201 #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ 202 break; 203 204 case 'n': 205 keepalive = 0; 206 break; 207 208 case 'p': 209 altlogin = optarg; 210 break; 211 212 case 'S': 213 #ifdef HAS_GETTOS 214 if ((tos = parsetos(optarg, "tcp")) < 0) 215 warnx("%s%s%s", 216 "bad TOS argument '", optarg, 217 "'; will try to use default TOS"); 218 #else 219 warnx("TOS option unavailable; -S flag not supported"); 220 #endif 221 break; 222 223 case 'u': 224 utmp_len = (size_t)atoi(optarg); 225 if (utmp_len >= sizeof(remote_hostname)) 226 utmp_len = sizeof(remote_hostname) - 1; 227 break; 228 229 case 'U': 230 registerd_host_only = 1; 231 break; 232 233 234 case '4': 235 family = AF_INET; 236 break; 237 238 #ifdef INET6 239 case '6': 240 family = AF_INET6; 241 break; 242 #endif 243 244 default: 245 warnx("%c: unknown option", ch); 246 /* FALLTHROUGH */ 247 case '?': 248 usage(); 249 /* NOTREACHED */ 250 } 251 } 252 253 argc -= optind; 254 argv += optind; 255 256 if (debug) { 257 int s, ns, foo, error; 258 const char *service = "telnet"; 259 struct addrinfo hints, *res; 260 261 if (argc > 1) { 262 usage(); 263 /* NOT REACHED */ 264 } else if (argc == 1) 265 service = *argv; 266 267 memset(&hints, 0, sizeof(hints)); 268 hints.ai_flags = AI_PASSIVE; 269 hints.ai_family = family; 270 hints.ai_socktype = SOCK_STREAM; 271 hints.ai_protocol = 0; 272 error = getaddrinfo(NULL, service, &hints, &res); 273 274 if (error) { 275 errx(1, "tcp/%s: %s\n", service, gai_strerror(error)); 276 if (error == EAI_SYSTEM) 277 errx(1, "tcp/%s: %s\n", service, strerror(errno)); 278 usage(); 279 } 280 281 s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 282 if (s < 0) 283 err(1, "socket"); 284 (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, 285 (char *)&on, sizeof(on)); 286 if (bind(s, res->ai_addr, res->ai_addrlen) < 0) 287 err(1, "bind"); 288 if (listen(s, 1) < 0) 289 err(1, "listen"); 290 foo = res->ai_addrlen; 291 ns = accept(s, res->ai_addr, &foo); 292 if (ns < 0) 293 err(1, "accept"); 294 (void) dup2(ns, 0); 295 (void) close(ns); 296 (void) close(s); 297 #ifdef convex 298 } else if (argc == 1) { 299 ; /* VOID*/ /* Just ignore the host/port name */ 300 #endif 301 } else if (argc > 0) { 302 usage(); 303 /* NOT REACHED */ 304 } 305 306 openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON); 307 fromlen = sizeof (from); 308 if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { 309 warn("getpeername"); 310 _exit(1); 311 } 312 if (keepalive && 313 setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, 314 (char *)&on, sizeof (on)) < 0) { 315 syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); 316 } 317 318 #if defined(IPPROTO_IP) && defined(IP_TOS) 319 if (from.ss_family == AF_INET) { 320 # if defined(HAS_GETTOS) 321 struct tosent *tp; 322 if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) 323 tos = tp->t_tos; 324 # endif 325 if (tos < 0) 326 tos = 020; /* Low Delay bit */ 327 if (tos 328 && (setsockopt(0, IPPROTO_IP, IP_TOS, 329 (char *)&tos, sizeof(tos)) < 0) 330 && (errno != ENOPROTOOPT) ) 331 syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); 332 } 333 #endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ 334 net = 0; 335 doit((struct sockaddr *)&from); 336 /* NOTREACHED */ 337 return(0); 338 } /* end of main */ 339 340 void 341 usage() 342 { 343 fprintf(stderr, "usage: telnetd"); 344 #ifdef BFTPDAEMON 345 fprintf(stderr, " [-B]"); 346 #endif 347 fprintf(stderr, " [-debug]"); 348 #ifdef DIAGNOSTICS 349 fprintf(stderr, " [-D (options|report|exercise|netdata|ptydata)]\n\t"); 350 #endif 351 fprintf(stderr, " [-h]"); 352 #if defined(LINEMODE) && defined(KLUDGELINEMODE) 353 fprintf(stderr, " [-k]"); 354 #endif 355 #ifdef LINEMODE 356 fprintf(stderr, " [-l]"); 357 #endif 358 fprintf(stderr, " [-n]"); 359 fprintf(stderr, "\n\t"); 360 #ifdef HAS_GETTOS 361 fprintf(stderr, " [-S tos]"); 362 #endif 363 fprintf(stderr, " [-u utmp_hostname_length] [-U]"); 364 fprintf(stderr, " [port]\n"); 365 exit(1); 366 } 367 368 /* 369 * getterminaltype 370 * 371 * Ask the other end to send along its terminal type and speed. 372 * Output is the variable terminaltype filled in. 373 */ 374 static unsigned char ttytype_sbbuf[] = { 375 IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE 376 }; 377 378 379 #define undef2 __unused 380 381 static int 382 getterminaltype(char *name undef2) 383 { 384 int retval = -1; 385 386 settimer(baseline); 387 388 send_do(TELOPT_TTYPE, 1); 389 send_do(TELOPT_TSPEED, 1); 390 send_do(TELOPT_XDISPLOC, 1); 391 send_do(TELOPT_NEW_ENVIRON, 1); 392 send_do(TELOPT_OLD_ENVIRON, 1); 393 while ( 394 his_will_wont_is_changing(TELOPT_TTYPE) || 395 his_will_wont_is_changing(TELOPT_TSPEED) || 396 his_will_wont_is_changing(TELOPT_XDISPLOC) || 397 his_will_wont_is_changing(TELOPT_NEW_ENVIRON) || 398 his_will_wont_is_changing(TELOPT_OLD_ENVIRON)) { 399 ttloop(); 400 } 401 if (his_state_is_will(TELOPT_TSPEED)) { 402 static unsigned char sb[] = 403 { IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE }; 404 405 output_datalen(sb, sizeof sb); 406 DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); 407 } 408 if (his_state_is_will(TELOPT_XDISPLOC)) { 409 static unsigned char sb[] = 410 { IAC, SB, TELOPT_XDISPLOC, TELQUAL_SEND, IAC, SE }; 411 412 output_datalen(sb, sizeof sb); 413 DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); 414 } 415 if (his_state_is_will(TELOPT_NEW_ENVIRON)) { 416 static unsigned char sb[] = 417 { IAC, SB, TELOPT_NEW_ENVIRON, TELQUAL_SEND, IAC, SE }; 418 419 output_datalen(sb, sizeof sb); 420 DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); 421 } 422 else if (his_state_is_will(TELOPT_OLD_ENVIRON)) { 423 static unsigned char sb[] = 424 { IAC, SB, TELOPT_OLD_ENVIRON, TELQUAL_SEND, IAC, SE }; 425 426 output_datalen(sb, sizeof sb); 427 DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); 428 } 429 if (his_state_is_will(TELOPT_TTYPE)) { 430 431 output_datalen(ttytype_sbbuf, sizeof ttytype_sbbuf); 432 DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2, 433 sizeof ttytype_sbbuf - 2);); 434 } 435 if (his_state_is_will(TELOPT_TSPEED)) { 436 while (sequenceIs(tspeedsubopt, baseline)) 437 ttloop(); 438 } 439 if (his_state_is_will(TELOPT_XDISPLOC)) { 440 while (sequenceIs(xdisplocsubopt, baseline)) 441 ttloop(); 442 } 443 if (his_state_is_will(TELOPT_NEW_ENVIRON)) { 444 while (sequenceIs(environsubopt, baseline)) 445 ttloop(); 446 } 447 if (his_state_is_will(TELOPT_OLD_ENVIRON)) { 448 while (sequenceIs(oenvironsubopt, baseline)) 449 ttloop(); 450 } 451 if (his_state_is_will(TELOPT_TTYPE)) { 452 char first[256], last[256]; 453 454 while (sequenceIs(ttypesubopt, baseline)) 455 ttloop(); 456 457 /* 458 * If the other side has already disabled the option, then 459 * we have to just go with what we (might) have already gotten. 460 */ 461 if (his_state_is_will(TELOPT_TTYPE) && !terminaltypeok(terminaltype)) { 462 (void) strncpy(first, terminaltype, sizeof(first)-1); 463 first[sizeof(first)-1] = '\0'; 464 for(;;) { 465 /* 466 * Save the unknown name, and request the next name. 467 */ 468 (void) strncpy(last, terminaltype, sizeof(last)-1); 469 last[sizeof(last)-1] = '\0'; 470 _gettermname(); 471 if (terminaltypeok(terminaltype)) 472 break; 473 if ((strncmp(last, terminaltype, sizeof(last)) == 0) || 474 his_state_is_wont(TELOPT_TTYPE)) { 475 /* 476 * We've hit the end. If this is the same as 477 * the first name, just go with it. 478 */ 479 if (strncmp(first, terminaltype, sizeof(first)) == 0) 480 break; 481 /* 482 * Get the terminal name one more time, so that 483 * RFC1091 compliant telnets will cycle back to 484 * the start of the list. 485 */ 486 _gettermname(); 487 if (strncmp(first, terminaltype, sizeof(first)) != 0) { 488 (void) strncpy(terminaltype, first, sizeof(terminaltype)-1); 489 terminaltype[sizeof(terminaltype)-1] = '\0'; 490 } 491 break; 492 } 493 } 494 } 495 } 496 return(retval); 497 } /* end of getterminaltype */ 498 499 static void 500 _gettermname(void) 501 { 502 /* 503 * If the client turned off the option, 504 * we can't send another request, so we 505 * just return. 506 */ 507 if (his_state_is_wont(TELOPT_TTYPE)) 508 return; 509 settimer(baseline); 510 output_datalen(ttytype_sbbuf, sizeof ttytype_sbbuf); 511 DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2, 512 sizeof ttytype_sbbuf - 2);); 513 while (sequenceIs(ttypesubopt, baseline)) 514 ttloop(); 515 } 516 517 int 518 terminaltypeok(char *s) 519 { 520 char buf[1024]; 521 522 if (terminaltype == NULL) 523 return(1); 524 525 /* 526 * tgetent() will return 1 if the type is known, and 527 * 0 if it is not known. If it returns -1, it couldn't 528 * open the database. But if we can't open the database, 529 * it won't help to say we failed, because we won't be 530 * able to verify anything else. So, we treat -1 like 1. 531 */ 532 if (tgetent(buf, s) == 0) 533 return(0); 534 return(1); 535 } 536 537 /* 538 * Get a pty, scan input lines. 539 */ 540 void 541 doit(struct sockaddr *who) 542 { 543 int err_; /* XXX */ 544 int ptynum; 545 546 /* 547 * Find an available pty to use. 548 */ 549 #ifndef convex 550 pty = getpty(&ptynum); 551 if (pty < 0) 552 fatal(net, "All network ports in use"); 553 #else 554 for (;;) { 555 char *lp; 556 557 if ((lp = getpty()) == NULL) 558 fatal(net, "Out of ptys"); 559 560 if ((pty = open(lp, 2)) >= 0) { 561 strlcpy(line,lp,sizeof(line)); 562 line[5] = 't'; 563 break; 564 } 565 } 566 #endif 567 568 /* get name of connected client */ 569 if (realhostname_sa(remote_hostname, sizeof(remote_hostname) - 1, 570 who, who->sa_len) == HOSTNAME_INVALIDADDR && registerd_host_only) 571 fatal(net, "Couldn't resolve your address into a host name.\r\n\ 572 Please contact your net administrator"); 573 remote_hostname[sizeof(remote_hostname) - 1] = '\0'; 574 575 trimdomain(remote_hostname, UT_HOSTSIZE); 576 if (!isdigit(remote_hostname[0]) && strlen(remote_hostname) > utmp_len) 577 err_ = getnameinfo(who, who->sa_len, remote_hostname, 578 sizeof(remote_hostname), NULL, 0, 579 NI_NUMERICHOST|NI_WITHSCOPEID); 580 /* XXX: do 'err_' check */ 581 582 (void) gethostname(host_name, sizeof(host_name) - 1); 583 host_name[sizeof(host_name) - 1] = '\0'; 584 hostname = host_name; 585 586 587 init_env(); 588 /* 589 * get terminal type. 590 */ 591 *user_name = 0; 592 level = getterminaltype(user_name); 593 if (setenv("TERM", terminaltype ? terminaltype : "network", 1) == -1) 594 syslog(LOG_ERR, "setenv: cannot set TERM=%s: %m", terminaltype ? terminaltype : "network"); 595 596 telnet(net, pty, remote_hostname); /* begin server process */ 597 598 /*NOTREACHED*/ 599 } /* end of doit */ 600 601 /* 602 * Main loop. Select from pty and network, and 603 * hand data to telnet receiver finite state machine. 604 */ 605 void 606 telnet(int f, int p, char *host) 607 { 608 int on = 1; 609 #define TABBUFSIZ 512 610 char defent[TABBUFSIZ]; 611 char defstrs[TABBUFSIZ]; 612 #undef TABBUFSIZ 613 char *HE; 614 char *HN; 615 char *IM; 616 int nfd; 617 618 /* 619 * Initialize the slc mapping table. 620 */ 621 get_slc_defaults(); 622 623 /* 624 * Do some tests where it is desireable to wait for a response. 625 * Rather than doing them slowly, one at a time, do them all 626 * at once. 627 */ 628 if (my_state_is_wont(TELOPT_SGA)) 629 send_will(TELOPT_SGA, 1); 630 /* 631 * Is the client side a 4.2 (NOT 4.3) system? We need to know this 632 * because 4.2 clients are unable to deal with TCP urgent data. 633 * 634 * To find out, we send out a "DO ECHO". If the remote system 635 * answers "WILL ECHO" it is probably a 4.2 client, and we note 636 * that fact ("WILL ECHO" ==> that the client will echo what 637 * WE, the server, sends it; it does NOT mean that the client will 638 * echo the terminal input). 639 */ 640 send_do(TELOPT_ECHO, 1); 641 642 #ifdef LINEMODE 643 if (his_state_is_wont(TELOPT_LINEMODE)) { 644 /* Query the peer for linemode support by trying to negotiate 645 * the linemode option. 646 */ 647 linemode = 0; 648 editmode = 0; 649 send_do(TELOPT_LINEMODE, 1); /* send do linemode */ 650 } 651 #endif /* LINEMODE */ 652 653 /* 654 * Send along a couple of other options that we wish to negotiate. 655 */ 656 send_do(TELOPT_NAWS, 1); 657 send_will(TELOPT_STATUS, 1); 658 flowmode = 1; /* default flow control state */ 659 restartany = -1; /* uninitialized... */ 660 send_do(TELOPT_LFLOW, 1); 661 662 /* 663 * Spin, waiting for a response from the DO ECHO. However, 664 * some REALLY DUMB telnets out there might not respond 665 * to the DO ECHO. So, we spin looking for NAWS, (most dumb 666 * telnets so far seem to respond with WONT for a DO that 667 * they don't understand...) because by the time we get the 668 * response, it will already have processed the DO ECHO. 669 * Kludge upon kludge. 670 */ 671 while (his_will_wont_is_changing(TELOPT_NAWS)) 672 ttloop(); 673 674 /* 675 * But... 676 * The client might have sent a WILL NAWS as part of its 677 * startup code; if so, we'll be here before we get the 678 * response to the DO ECHO. We'll make the assumption 679 * that any implementation that understands about NAWS 680 * is a modern enough implementation that it will respond 681 * to our DO ECHO request; hence we'll do another spin 682 * waiting for the ECHO option to settle down, which is 683 * what we wanted to do in the first place... 684 */ 685 if (his_want_state_is_will(TELOPT_ECHO) && 686 his_state_is_will(TELOPT_NAWS)) { 687 while (his_will_wont_is_changing(TELOPT_ECHO)) 688 ttloop(); 689 } 690 /* 691 * On the off chance that the telnet client is broken and does not 692 * respond to the DO ECHO we sent, (after all, we did send the 693 * DO NAWS negotiation after the DO ECHO, and we won't get here 694 * until a response to the DO NAWS comes back) simulate the 695 * receipt of a will echo. This will also send a WONT ECHO 696 * to the client, since we assume that the client failed to 697 * respond because it believes that it is already in DO ECHO 698 * mode, which we do not want. 699 */ 700 if (his_want_state_is_will(TELOPT_ECHO)) { 701 DIAG(TD_OPTIONS, output_data("td: simulating recv\r\n")); 702 willoption(TELOPT_ECHO); 703 } 704 705 /* 706 * Finally, to clean things up, we turn on our echo. This 707 * will break stupid 4.2 telnets out of local terminal echo. 708 */ 709 710 if (my_state_is_wont(TELOPT_ECHO)) 711 send_will(TELOPT_ECHO, 1); 712 713 /* 714 * Turn on packet mode 715 */ 716 (void) ioctl(p, TIOCPKT, (char *)&on); 717 718 #if defined(LINEMODE) && defined(KLUDGELINEMODE) 719 /* 720 * Continuing line mode support. If client does not support 721 * real linemode, attempt to negotiate kludge linemode by sending 722 * the do timing mark sequence. 723 */ 724 if (lmodetype < REAL_LINEMODE) 725 send_do(TELOPT_TM, 1); 726 #endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ 727 728 /* 729 * Call telrcv() once to pick up anything received during 730 * terminal type negotiation, 4.2/4.3 determination, and 731 * linemode negotiation. 732 */ 733 telrcv(); 734 735 (void) ioctl(f, FIONBIO, (char *)&on); 736 (void) ioctl(p, FIONBIO, (char *)&on); 737 738 #if defined(SO_OOBINLINE) 739 (void) setsockopt(net, SOL_SOCKET, SO_OOBINLINE, 740 (char *)&on, sizeof on); 741 #endif /* defined(SO_OOBINLINE) */ 742 743 #ifdef SIGTSTP 744 (void) signal(SIGTSTP, SIG_IGN); 745 #endif 746 #ifdef SIGTTOU 747 /* 748 * Ignoring SIGTTOU keeps the kernel from blocking us 749 * in ttioct() in /sys/tty.c. 750 */ 751 (void) signal(SIGTTOU, SIG_IGN); 752 #endif 753 754 (void) signal(SIGCHLD, cleanup); 755 756 #ifdef TIOCNOTTY 757 { 758 int t; 759 t = open(_PATH_TTY, O_RDWR); 760 if (t >= 0) { 761 (void) ioctl(t, TIOCNOTTY, (char *)0); 762 (void) close(t); 763 } 764 } 765 #endif 766 767 /* 768 * Show banner that getty never gave. 769 * 770 * We put the banner in the pty input buffer. This way, it 771 * gets carriage return null processing, etc., just like all 772 * other pty --> client data. 773 */ 774 775 if (getent(defent, "default") == 1) { 776 char *cp=defstrs; 777 778 HE = Getstr("he", &cp); 779 HN = Getstr("hn", &cp); 780 IM = Getstr("im", &cp); 781 if (HN && *HN) 782 (void) strlcpy(host_name, HN, sizeof(host_name)); 783 if (IM == 0) 784 IM = strdup(""); 785 } else { 786 IM = strdup(DEFAULT_IM); 787 HE = 0; 788 } 789 edithost(HE, host_name); 790 if (hostinfo && *IM) 791 putf(IM, ptyibuf2); 792 793 if (pcc) 794 (void) strncat(ptyibuf2, ptyip, pcc+1); 795 ptyip = ptyibuf2; 796 pcc = strlen(ptyip); 797 #ifdef LINEMODE 798 /* 799 * Last check to make sure all our states are correct. 800 */ 801 init_termbuf(); 802 localstat(); 803 #endif /* LINEMODE */ 804 805 DIAG(TD_REPORT, output_data("td: Entering processing loop\r\n")); 806 807 /* 808 * Startup the login process on the slave side of the terminal 809 * now. We delay this until here to insure option negotiation 810 * is complete. 811 */ 812 startslave(host, level, user_name); 813 814 nfd = ((f > p) ? f : p) + 1; 815 for (;;) { 816 fd_set ibits, obits, xbits; 817 int c; 818 819 if (ncc < 0 && pcc < 0) 820 break; 821 822 FD_ZERO(&ibits); 823 FD_ZERO(&obits); 824 FD_ZERO(&xbits); 825 /* 826 * Never look for input if there's still 827 * stuff in the corresponding output buffer 828 */ 829 if (nfrontp - nbackp || pcc > 0) { 830 FD_SET(f, &obits); 831 } else { 832 FD_SET(p, &ibits); 833 } 834 if (pfrontp - pbackp || ncc > 0) { 835 FD_SET(p, &obits); 836 } else { 837 FD_SET(f, &ibits); 838 } 839 if (!SYNCHing) { 840 FD_SET(f, &xbits); 841 } 842 if ((c = select(nfd, &ibits, &obits, &xbits, 843 (struct timeval *)0)) < 1) { 844 if (c == -1) { 845 if (errno == EINTR) { 846 continue; 847 } 848 } 849 sleep(5); 850 continue; 851 } 852 853 /* 854 * Any urgent data? 855 */ 856 if (FD_ISSET(net, &xbits)) { 857 SYNCHing = 1; 858 } 859 860 /* 861 * Something to read from the network... 862 */ 863 if (FD_ISSET(net, &ibits)) { 864 #if !defined(SO_OOBINLINE) 865 /* 866 * In 4.2 (and 4.3 beta) systems, the 867 * OOB indication and data handling in the kernel 868 * is such that if two separate TCP Urgent requests 869 * come in, one byte of TCP data will be overlaid. 870 * This is fatal for Telnet, but we try to live 871 * with it. 872 * 873 * In addition, in 4.2 (and...), a special protocol 874 * is needed to pick up the TCP Urgent data in 875 * the correct sequence. 876 * 877 * What we do is: if we think we are in urgent 878 * mode, we look to see if we are "at the mark". 879 * If we are, we do an OOB receive. If we run 880 * this twice, we will do the OOB receive twice, 881 * but the second will fail, since the second 882 * time we were "at the mark", but there wasn't 883 * any data there (the kernel doesn't reset 884 * "at the mark" until we do a normal read). 885 * Once we've read the OOB data, we go ahead 886 * and do normal reads. 887 * 888 * There is also another problem, which is that 889 * since the OOB byte we read doesn't put us 890 * out of OOB state, and since that byte is most 891 * likely the TELNET DM (data mark), we would 892 * stay in the TELNET SYNCH (SYNCHing) state. 893 * So, clocks to the rescue. If we've "just" 894 * received a DM, then we test for the 895 * presence of OOB data when the receive OOB 896 * fails (and AFTER we did the normal mode read 897 * to clear "at the mark"). 898 */ 899 if (SYNCHing) { 900 int atmark; 901 902 (void) ioctl(net, SIOCATMARK, (char *)&atmark); 903 if (atmark) { 904 ncc = recv(net, netibuf, sizeof (netibuf), MSG_OOB); 905 if ((ncc == -1) && (errno == EINVAL)) { 906 ncc = read(net, netibuf, sizeof (netibuf)); 907 if (sequenceIs(didnetreceive, gotDM)) { 908 SYNCHing = stilloob(net); 909 } 910 } 911 } else { 912 ncc = read(net, netibuf, sizeof (netibuf)); 913 } 914 } else { 915 ncc = read(net, netibuf, sizeof (netibuf)); 916 } 917 settimer(didnetreceive); 918 #else /* !defined(SO_OOBINLINE)) */ 919 ncc = read(net, netibuf, sizeof (netibuf)); 920 #endif /* !defined(SO_OOBINLINE)) */ 921 if (ncc < 0 && errno == EWOULDBLOCK) 922 ncc = 0; 923 else { 924 if (ncc <= 0) { 925 break; 926 } 927 netip = netibuf; 928 } 929 DIAG((TD_REPORT | TD_NETDATA), 930 output_data("td: netread %d chars\r\n", ncc)); 931 DIAG(TD_NETDATA, printdata("nd", netip, ncc)); 932 } 933 934 /* 935 * Something to read from the pty... 936 */ 937 if (FD_ISSET(p, &ibits)) { 938 pcc = read(p, ptyibuf, BUFSIZ); 939 /* 940 * On some systems, if we try to read something 941 * off the master side before the slave side is 942 * opened, we get EIO. 943 */ 944 if (pcc < 0 && (errno == EWOULDBLOCK || 945 #ifdef EAGAIN 946 errno == EAGAIN || 947 #endif 948 errno == EIO)) { 949 pcc = 0; 950 } else { 951 if (pcc <= 0) 952 break; 953 #ifdef LINEMODE 954 /* 955 * If ioctl from pty, pass it through net 956 */ 957 if (ptyibuf[0] & TIOCPKT_IOCTL) { 958 copy_termbuf(ptyibuf+1, pcc-1); 959 localstat(); 960 pcc = 1; 961 } 962 #endif /* LINEMODE */ 963 if (ptyibuf[0] & TIOCPKT_FLUSHWRITE) { 964 netclear(); /* clear buffer back */ 965 #ifndef NO_URGENT 966 /* 967 * There are client telnets on some 968 * operating systems get screwed up 969 * royally if we send them urgent 970 * mode data. 971 */ 972 output_data("%c%c", IAC, DM); 973 neturg = nfrontp-1; /* off by one XXX */ 974 DIAG(TD_OPTIONS, 975 printoption("td: send IAC", DM)); 976 977 #endif 978 } 979 if (his_state_is_will(TELOPT_LFLOW) && 980 (ptyibuf[0] & 981 (TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))) { 982 int newflow = 983 ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0; 984 if (newflow != flowmode) { 985 flowmode = newflow; 986 output_data("%c%c%c%c%c%c", 987 IAC, SB, TELOPT_LFLOW, 988 flowmode ? LFLOW_ON 989 : LFLOW_OFF, 990 IAC, SE); 991 DIAG(TD_OPTIONS, printsub('>', 992 (unsigned char *)nfrontp-4, 993 4);); 994 } 995 } 996 pcc--; 997 ptyip = ptyibuf+1; 998 } 999 } 1000 1001 while (pcc > 0) { 1002 if ((&netobuf[BUFSIZ] - nfrontp) < 2) 1003 break; 1004 c = *ptyip++ & 0377, pcc--; 1005 if (c == IAC) 1006 output_data("%c", c); 1007 output_data("%c", c); 1008 if ((c == '\r') && (my_state_is_wont(TELOPT_BINARY))) { 1009 if (pcc > 0 && ((*ptyip & 0377) == '\n')) { 1010 output_data("%c", *ptyip++ & 0377); 1011 pcc--; 1012 } else 1013 output_data("%c", '\0'); 1014 } 1015 } 1016 1017 if (FD_ISSET(f, &obits) && (nfrontp - nbackp) > 0) 1018 netflush(); 1019 if (ncc > 0) 1020 telrcv(); 1021 if (FD_ISSET(p, &obits) && (pfrontp - pbackp) > 0) 1022 ptyflush(); 1023 } 1024 cleanup(0); 1025 } /* end of telnet */ 1026 1027 #ifndef TCSIG 1028 # ifdef TIOCSIG 1029 # define TCSIG TIOCSIG 1030 # endif 1031 #endif 1032 1033 /* 1034 * Send interrupt to process on other side of pty. 1035 * If it is in raw mode, just write NULL; 1036 * otherwise, write intr char. 1037 */ 1038 void 1039 interrupt(void) 1040 { 1041 ptyflush(); /* half-hearted */ 1042 1043 #ifdef TCSIG 1044 (void) ioctl(pty, TCSIG, (char *)SIGINT); 1045 #else /* TCSIG */ 1046 init_termbuf(); 1047 *pfrontp++ = slctab[SLC_IP].sptr ? 1048 (unsigned char)*slctab[SLC_IP].sptr : '\177'; 1049 #endif /* TCSIG */ 1050 } 1051 1052 /* 1053 * Send quit to process on other side of pty. 1054 * If it is in raw mode, just write NULL; 1055 * otherwise, write quit char. 1056 */ 1057 void 1058 sendbrk(void) 1059 { 1060 ptyflush(); /* half-hearted */ 1061 #ifdef TCSIG 1062 (void) ioctl(pty, TCSIG, (char *)SIGQUIT); 1063 #else /* TCSIG */ 1064 init_termbuf(); 1065 *pfrontp++ = slctab[SLC_ABORT].sptr ? 1066 (unsigned char)*slctab[SLC_ABORT].sptr : '\034'; 1067 #endif /* TCSIG */ 1068 } 1069 1070 void 1071 sendsusp(void) 1072 { 1073 #ifdef SIGTSTP 1074 ptyflush(); /* half-hearted */ 1075 # ifdef TCSIG 1076 (void) ioctl(pty, TCSIG, (char *)SIGTSTP); 1077 # else /* TCSIG */ 1078 *pfrontp++ = slctab[SLC_SUSP].sptr ? 1079 (unsigned char)*slctab[SLC_SUSP].sptr : '\032'; 1080 # endif /* TCSIG */ 1081 #endif /* SIGTSTP */ 1082 } 1083 1084 /* 1085 * When we get an AYT, if ^T is enabled, use that. Otherwise, 1086 * just send back "[Yes]". 1087 */ 1088 void 1089 recv_ayt(void) 1090 { 1091 #if defined(SIGINFO) && defined(TCSIG) 1092 if (slctab[SLC_AYT].sptr && *slctab[SLC_AYT].sptr != _POSIX_VDISABLE) { 1093 (void) ioctl(pty, TCSIG, (char *)SIGINFO); 1094 return; 1095 } 1096 #endif 1097 output_data("\r\n[Yes]\r\n"); 1098 } 1099 1100 void 1101 doeof(void) 1102 { 1103 init_termbuf(); 1104 1105 #if defined(LINEMODE) && defined(USE_TERMIO) && (VEOF == VMIN) 1106 if (!tty_isediting()) { 1107 extern char oldeofc; 1108 *pfrontp++ = oldeofc; 1109 return; 1110 } 1111 #endif 1112 *pfrontp++ = slctab[SLC_EOF].sptr ? 1113 (unsigned char)*slctab[SLC_EOF].sptr : '\004'; 1114 } 1115