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