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