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