1 /*
2  * Copyright (c) 1993-2021 Paul Mattes.
3  * Copyright (c) 2004, Don Russell.
4  * Copyright (c) 1990, Jeff Sparkes.
5  * Copyright (c) 1989, Georgia Tech Research Corporation (GTRC), Atlanta,
6  *  GA 30332.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *     * Redistributions of source code must retain the above copyright
13  *       notice, this list of conditions and the following disclaimer.
14  *     * Redistributions in binary form must reproduce the above copyright
15  *       notice, this list of conditions and the following disclaimer in the
16  *       documentation and/or other materials provided with the distribution.
17  *     * Neither the names of Paul Mattes, Don Russell, Jeff Sparkes, GTRC
18  *       nor their contributors may be used to endorse or promote products
19  *       derived from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY PAUL MATTES, DON RUSSELL, JEFF SPARKES AND
22  * GTRC "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PAUL MATTES,
25  * DON RUSSELL, JEFF SPARKES OR GTRC BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
29  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 /*
35  *	telnet.c
36  *		This module initializes and manages a telnet socket to
37  *		the given IBM host.
38  */
39 
40 #include "globals.h"
41 
42 #if !defined(_WIN32) /*[*/
43 # include <sys/ioctl.h>
44 # include <netinet/in.h>
45 #endif /*]*/
46 #define TELCMDS 1
47 #define TELOPTS 1
48 #include "arpa_telnet.h"
49 #if !defined(_WIN32) /*[*/
50 # include <arpa/inet.h>
51 #endif /*]*/
52 #include <errno.h>
53 #include <fcntl.h>
54 #if !defined(_WIN32) /*[*/
55 # include <netdb.h>
56 #endif /*]*/
57 #include <stdint.h>
58 #include "tn3270e.h"
59 #include "3270ds.h"
60 
61 #include "appres.h"
62 
63 #include "actions.h"
64 #include "b3270proto.h"
65 #include "b8.h"
66 #include "ctlrc.h"
67 #include "host.h"
68 #include "indent_s.h"
69 #include "kybd.h"
70 #include "lazya.h"
71 #include "linemode.h"
72 #include "names.h"
73 #include "nvt.h"
74 #include "popups.h"
75 #include "proxy.h"
76 #include "resolver.h"
77 #include "sio.h"
78 #include "sioc.h"
79 #include "split_host.h"
80 #include "stats.h"
81 #include "status.h"
82 #include "task.h"
83 #include "telnet.h"
84 #include "telnet_core.h"
85 #include "telnet_gui.h"
86 #include "telnet_private.h"
87 #include "telnet_sio.h"
88 #include "tls_passwd_gui.h"
89 #include "trace.h"
90 #include "unicodec.h"
91 #include "utils.h"
92 #include "w3misc.h"
93 #include "xio.h"
94 
95 #if !defined(TELOPT_NAWS) /*[*/
96 # define TELOPT_NAWS	31
97 #endif /*]*/
98 
99 #if !defined(TELOPT_STARTTLS) /*[*/
100 # define TELOPT_STARTTLS	46
101 #endif /*]*/
102 #define TLS_FOLLOWS	1
103 
104 #define BUFSZ		32768
105 #define TRACELINE	72
106 
107 #define N_OPTS		256
108 
109 /* Globals */
110 char    	*hostname = NULL;
111 time_t          ns_time;
112 int             ns_brcvd;
113 int             ns_rrcvd;
114 int             ns_bsent;
115 int             ns_rsent;
116 unsigned char  *obuf;		/* 3270 output buffer */
117 unsigned char  *obptr = (unsigned char *) NULL;
118 bool            linemode = true;
119 #if defined(LOCAL_PROCESS) /*[*/
120 bool		local_process = false;
121 #endif /*]*/
122 char           *termtype;
123 struct timeval	net_last_recv_ts;
124 
125 const char *telquals[3] = { "IS", "SEND", "INFO" };
126 
127 /* Statics */
128 static socket_t sock = INVALID_SOCKET;	/* active socket */
129 #if defined(_WIN32) /*[*/
130 static HANDLE	sock_handle = INVALID_HANDLE_VALUE;
131 #endif /*]*/
132 static unsigned char myopts[N_OPTS], hisopts[N_OPTS];
133 			/* telnet option flags */
134 static bool did_ne_send;
135 static bool deferred_will_ttype;
136 static unsigned char *ibuf = (unsigned char *) NULL;
137 			/* 3270 input buffer */
138 static unsigned char *ibptr;
139 static int      ibuf_size = 0;	/* size of ibuf */
140 static unsigned char *obuf_base = NULL;
141 static int	obuf_size = 0;
142 static unsigned char *netrbuf = NULL;
143 			/* network input buffer */
144 static unsigned char *sbbuf = NULL;
145 			/* telnet sub-option buffer */
146 static unsigned char *sbptr;
147 static unsigned char telnet_state;
148 static int      syncing;
149 #if !defined(_WIN32) /*[*/
150 static ioid_t output_id = NULL_IOID;
151 #endif /*]*/
152 static ioid_t	connect_timeout_id = NULL_IOID;	/* explicit Connect timeout */
153 static ioid_t	nop_timeout_id = NULL_IOID;
154 static char     ttype_tmpval[13];
155 
156 static unsigned short e_xmit_seq; /* transmit sequence number */
157 static int response_required;
158 
159 static size_t   nvt_data = 0;
160 static int	tn3270e_negotiated = 0;
161 static enum { E_UNBOUND, E_3270, E_NVT, E_SSCP } tn3270e_submode = E_UNBOUND;
162 static int	tn3270e_bound = 0;
163 static unsigned char *bind_image = NULL;
164 static size_t	bind_image_len = 0;
165 static char	*plu_name = NULL;
166 static int	maxru_sec = 0;
167 static int	maxru_pri = 0;
168 static int	bind_rd = 0;
169 static int	bind_cd = 0;
170 static int	bind_ra = 0;
171 static int	bind_ca = 0;
172 #define BIND_DIMS_PRESENT	0x1	/* BIND included screen dimensions */
173 #define BIND_DIMS_ALT		0x2	/* BIND included alternate size */
174 #define BIND_DIMS_VALID		0x4	/* BIND screen sizes were valid */
175 static unsigned	bind_state = 0;
176 static char	**lus = NULL;
177 static char	**curr_lu = NULL;
178 static char	*try_lu = NULL;
179 
180 static proxytype_t proxy_type = PT_NONE;
181 static bool	proxy_pending = false;
182 static char	*proxy_user = NULL;
183 static char	*proxy_host = NULL;
184 static char	*proxy_portname = NULL;
185 static unsigned short proxy_port = 0;
186 
187 static b8_t e_funcs;		/* negotiated TN3270E functions */
188 
189 static bool	secure_connection;
190 static char	*net_accept;
191 
192 static enum cstate starttls_pending = NOT_CONNECTED;
193 
194 static bool telnet_fsm(unsigned char c);
195 static void net_rawout(unsigned const char *buf, size_t len);
196 static void check_in3270(void);
197 static void store3270in(unsigned char c);
198 static void check_linemode(bool init);
199 static int non_blocking(bool on);
200 static void net_connected(void);
201 static void connection_complete(void);
202 static int tn3270e_negotiate(void);
203 static int process_eor(void);
204 static const char *tn3270e_function_names(const unsigned char *, int);
205 static void tn3270e_subneg_send(unsigned char, b8_t *);
206 static void tn3270e_fdecode(const unsigned char *, int, b8_t *);
207 static void tn3270e_ack(void);
208 static void tn3270e_nak(enum pds);
209 static void net_starttls_continue(void);
210 
211 static const char *nnn(int c);
212 
213 static void net_hexnvt_out_framed(unsigned char *buf, int len, bool framed);
214 
215 /* telnet states */
216 #define TNS_DATA	0	/* receiving data */
217 #define TNS_IAC		1	/* got an IAC */
218 #define TNS_WILL	2	/* got an IAC WILL */
219 #define TNS_WONT	3	/* got an IAC WONT */
220 #define TNS_DO		4	/* got an IAC DO */
221 #define TNS_DONT	5	/* got an IAC DONT */
222 #define TNS_SB		6	/* got an IAC SB */
223 #define TNS_SB_IAC	7	/* got an IAC after an IAC SB */
224 
225 /* telnet predefined messages */
226 static unsigned char	do_opt[]	= {
227 	IAC, DO, '_' };
228 static unsigned char	dont_opt[]	= {
229 	IAC, DONT, '_' };
230 static unsigned char	will_opt[]	= {
231 	IAC, WILL, '_' };
232 static unsigned char	wont_opt[]	= {
233 	IAC, WONT, '_' };
234 static unsigned char	functions_req[] = {
235 	IAC, SB, TELOPT_TN3270E, TN3270E_OP_FUNCTIONS };
236 
237 static const char *reason_code[8] = { "CONN-PARTNER", "DEVICE-IN-USE",
238 	"INV-ASSOCIATE", "INV-NAME", "INV-DEVICE-TYPE", "TYPE-NAME-ERROR",
239 	"UNKNOWN-ERROR", "UNSUPPORTED-REQ" };
240 #  define rsn(n)	(((n) <= TN3270E_REASON_UNSUPPORTED_REQ)? \
241 			reason_code[(n)]: "??")
242 static const char *function_name[5] = { "BIND-IMAGE", "DATA-STREAM-CTL",
243 	"RESPONSES", "SCS-CTL-CODES", "SYSREQ" };
244 # define fnn(n)	(((n) <= TN3270E_FUNC_SYSREQ)? \
245 			function_name[(n)]: "??")
246 static const char *data_type[9] = { "3270-DATA", "SCS-DATA", "RESPONSE",
247 	"BIND-IMAGE", "UNBIND", "NVT-DATA", "REQUEST", "SSCP-LU-DATA",
248 	"PRINT-EOJ" };
249 # define e_dt(n)	(((n) <= TN3270E_DT_PRINT_EOJ)? \
250 			data_type[(n)]: "??")
251 static const char *req_flag[1] = { " ERR-COND-CLEARED" };
252 # define e_rq(fn, n) (((fn) == TN3270E_DT_REQUEST)? \
253 			(((n) <= TN3270E_RQF_ERR_COND_CLEARED)? \
254 			req_flag[(n)]: " ??"): "")
255 static const char *hrsp_flag[3] = { "NO-RESPONSE", "ERROR-RESPONSE",
256 	"ALWAYS-RESPONSE" };
257 # define e_hrsp(n) (((n) <= TN3270E_RSF_ALWAYS_RESPONSE)? \
258 			hrsp_flag[(n)]: "??")
259 static const char *trsp_flag[2] = { "POSITIVE-RESPONSE", "NEGATIVE-RESPONSE" };
260 # define e_trsp(n) (((n) <= TN3270E_RSF_NEGATIVE_RESPONSE)? \
261 			trsp_flag[(n)]: "??")
262 # define e_rsp(fn, n) (((fn) == TN3270E_DT_RESPONSE)? e_trsp(n): e_hrsp(n))
263 const char *state_name[NUM_CSTATE] = {
264     CstateNotConnected,
265     CstateReconnecting,
266     CstateTlsPasswordPending,
267     CstateResolving,
268     CstateTcpPending,
269     CstateTlsPending,
270     CstateProxyPending,
271     CstateTelnetPending,
272     CstateConnectedNvt,
273     CstateConnectedNvtCharmode,
274     CstateConnected3270,
275     CstateConnectedUnbound,
276     CstateConnectedEnvt,
277     CstateConnectedSscp,
278     CstateConnectedTn3270e
279 };
280 
281 #if !defined(_WIN32) /*[*/
282 # define XMIT_ROWS	((appres.c3270.altscreen)? MODEL_2_ROWS: maxROWS)
283 # define XMIT_COLS	((appres.c3270.altscreen)? MODEL_2_COLS: maxCOLS)
284 #else /*][*/
285 # define XMIT_ROWS	maxROWS
286 # define XMIT_COLS	maxCOLS
287 #endif /*]*/
288 
289 sio_t sio = NULL;
290 
291 static void continue_tls(unsigned char *sbbuf, int len);
292 static bool refused_tls = false;
293 static bool nested_tls = false;
294 static bool any_host_data = false;
295 static bool need_tls_follows = false;
296 
297 static bool net_connect_pending;
298 
299 #if !defined(_WIN32) /*[*/
300 static void output_possible(iosrc_t fd, ioid_t id);
301 #endif /*]*/
302 
303 #if defined(_WIN32) /*[*/
304 # define socket_errno()	WSAGetLastError()
305 # define socket_strerror(n) win32_strerror(n)
306 # define SE_EWOULDBLOCK	WSAEWOULDBLOCK
307 # define SE_ECONNRESET	WSAECONNRESET
308 # define SE_EINTR	WSAEINTR
309 # define SE_EAGAIN	WSAEINPROGRESS
310 # define SE_EPIPE	WSAECONNABORTED
311 # define SE_EINPROGRESS	WSAEINPROGRESS
312 # define SOCK_IOCTL(s, f, v)	ioctlsocket(s, f, (DWORD *)v)
313 # define IOCTL_T	u_long
314 #else /*][*/
315 # define socket_errno()	errno
316 # define socket_strerror(n) strerror(n)
317 # define SE_EWOULDBLOCK	EWOULDBLOCK
318 # define SE_ECONNRESET	ECONNRESET
319 # define SE_EINTR	EINTR
320 # define SE_EAGAIN	EAGAIN
321 # define SE_EPIPE	EPIPE
322 # if defined(EINPROGRESS) /*[*/
323 #  define SE_EINPROGRESS	EINPROGRESS
324 # endif /*]*/
325 # define SOCK_IOCTL	ioctl
326 # define IOCTL_T	int
327 #endif /*]*/
328 
329 #if defined(SE_EINPROGRESS) /*[*/
330 # define IS_EINPROGRESS(e)	((e) == SE_EINPROGRESS)
331 #else /*][*/
332 # define IS_EINPROGRESS(e)	false
333 #endif /*]*/
334 
335 typedef union {
336     struct sockaddr sa;
337     struct sockaddr_in sin;
338 #if defined(X3270_IPV6) /*[*/
339     struct sockaddr_in6 sin6;
340 #endif /*]*/
341 } sockaddr_46_t;
342 
343 #define NUM_HA	4
344 static sockaddr_46_t haddr[NUM_HA];
345 static socklen_t ha_len[NUM_HA] = {
346     sizeof(haddr[0]), sizeof(haddr[0]), sizeof(haddr[0]), sizeof(haddr[0])
347 };
348 static int num_ha = 0;
349 static int ha_ix = 0;
350 static int resolver_pipe[2] = { -1, -1 };
351 static int resolver_slot = -1;
352 static iosrc_t resolver_event = INVALID_IOSRC;
353 
354 #if defined(_WIN32) /*[*/
355 void
popup_a_sockerr(const char * fmt,...)356 popup_a_sockerr(const char *fmt, ...)
357 {
358     va_list args;
359     char *buffer;
360 
361     va_start(args, fmt);
362     buffer = vlazyaf(fmt, args);
363     va_end(args);
364     connect_error("%s: %s", buffer, win32_strerror(socket_errno()));
365 }
366 #else /*][*/
367 void
popup_a_sockerr(const char * fmt,...)368 popup_a_sockerr(const char *fmt, ...)
369 {
370     va_list args;
371     char *buffer;
372 
373     va_start(args, fmt);
374     buffer = vlazyaf(fmt, args);
375     va_end(args);
376     connect_errno(errno, "%s", buffer);
377 }
378 #endif /*]*/
379 
380 /* The host connection timed out. */
381 static void
connect_timed_out(ioid_t id _is_unused)382 connect_timed_out(ioid_t id _is_unused)
383 {
384     connect_error("Host connection timed out");
385     connect_timeout_id = NULL_IOID;
386     host_disconnect(true);
387 }
388 
389 /* Connect to one of the addresses in haddr[]. */
390 static iosrc_t
connect_to(int ix,bool noisy,bool * pending)391 connect_to(int ix, bool noisy, bool *pending)
392 {
393     int			on = 1;
394     char		hn[256];
395     char		pn[256];
396     char		*errmsg;
397 #if defined(OMTU) /*[*/
398     int			mtu = OMTU;
399 #endif /*]*/
400 #   define close_fail	{ SOCK_CLOSE(sock); \
401     			  sock = INVALID_SOCKET; \
402     			  return INVALID_IOSRC; \
403 			}
404 
405     /* create the socket */
406     if ((sock = socket(haddr[ix].sa.sa_family, SOCK_STREAM, IPPROTO_TCP)) ==
407 	    INVALID_SOCKET) {
408 	popup_a_sockerr("socket");
409 	return INVALID_IOSRC;
410     }
411 
412     /* set options for inline out-of-band data and keepalives */
413     if (setsockopt(sock, SOL_SOCKET, SO_OOBINLINE, (char *)&on,
414 		sizeof(on)) < 0) {
415 	popup_a_sockerr("setsockopt(SO_OOBINLINE)");
416 	close_fail;
417     }
418     if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&on,
419 		sizeof(on)) < 0) {
420 	popup_a_sockerr("setsockopt(SO_KEEPALIVE)");
421 	close_fail;
422     }
423 #if defined(OMTU) /*[*/
424     if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&mtu,
425 		sizeof(mtu)) < 0) {
426 	popup_a_sockerr("setsockopt(SO_SNDBUF)");
427 	close_fail;
428     }
429 #endif /*]*/
430 
431     /* set the socket to be non-delaying */
432     if (non_blocking(true) < 0) {
433 	close_fail;
434     }
435 
436 #if !defined(_WIN32) /*[*/
437     /* don't share the socket with our children */
438     fcntl(sock, F_SETFD, 1);
439 #endif /*]*/
440 
441     /* Init TLS. */
442     if (HOST_FLAG(TLS_HOST)) {
443 	if (!sio_supported()) {
444 	    popup_an_error("TLS not supported\n");
445 	    close_fail;
446 	}
447     }
448 
449     if (numeric_host_and_port(&haddr[ix].sa, ha_len[ix], hn, sizeof(hn), pn,
450 		sizeof(pn), &errmsg)) {
451 	vtrace("Trying %s, port %s...\n", hn, pn);
452 	telnet_gui_connecting(hn, pn);
453     }
454 
455     /* Set an explicit timeout, if configured. */
456     if (appres.connect_timeout) {
457 	connect_timeout_id = AddTimeOut(appres.connect_timeout * 1000,
458 		connect_timed_out);
459     }
460 
461     /* connect */
462     if (connect(sock, &haddr[ix].sa, ha_len[ix]) == -1) {
463 	if (socket_errno() == SE_EWOULDBLOCK ||
464 		IS_EINPROGRESS(socket_errno())) {
465 	    vtrace("TCP connection pending.\n");
466 	    *pending = true;
467 #if !defined(_WIN32) /*[*/
468 	    output_id = AddOutput(sock, output_possible);
469 #endif /*]*/
470 	} else {
471 	    if (noisy) {
472 		popup_a_sockerr(AnConnect "() to %s%s, port %d",
473 			(proxy_type != PT_NONE)? "proxy ": "",
474 			(proxy_type != PT_NONE)? proxy_host : hostname,
475 			(proxy_type != PT_NONE)? proxy_port : current_port);
476 	    }
477 	    close_fail;
478 	}
479     } else {
480 	net_connected();
481 
482 	/* net_connected() can cause the connection to fail. */
483 	if (sock == INVALID_SOCKET) {
484 	    close_fail;
485 	}
486     }
487 
488     /* all done */
489 #if defined(_WIN32) /*[*/
490     sock_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
491     if (sock_handle == NULL) {
492 	fprintf(stderr, "Cannot create socket handle: %s\n",
493 		win32_strerror(GetLastError()));
494 	x3270_exit(1);
495     }
496     if (WSAEventSelect(sock, sock_handle, FD_READ | FD_CONNECT | FD_CLOSE)
497 	    != 0) {
498 	fprintf(stderr, "WSAEventSelect failed: %s\n",
499 		win32_strerror(GetLastError()));
500 	x3270_exit(1);
501     }
502 
503     return sock_handle;
504 #else /*][*/
505     return sock;
506 #endif /*]*/
507 }
508 
509 /* Complete a connection, now that the hostname has been resolved. */
510 static net_connect_t
finish_connect(iosrc_t * iosrc)511 finish_connect(iosrc_t *iosrc)
512 {
513     iosrc_t s;
514 
515     /* Set up the TLS context, whether this is an TLS host or not. */
516     if (sio_supported()) {
517 	bool pending = false;
518 
519 	sio = sio_init_wrapper(NULL, HOST_FLAG(NO_VERIFY_CERT_HOST),
520 		net_accept, &pending);
521 	if (sio == NULL) {
522 	    if (pending) {
523 		net_connect_pending = true;
524 		return NC_TLS_PASS;
525 	    }
526 	    net_disconnect(false);
527 	    return NC_FAILED;
528 	}
529     }
530 
531     /* Try each of the haddrs. */
532     ha_ix = 0;
533     while (ha_ix < num_ha) {
534 	bool pending = false;
535 
536 	if ((s = connect_to(ha_ix, (ha_ix == num_ha - 1),
537 			&pending)) != INVALID_IOSRC) {
538 	    *iosrc = s;
539 	    return pending? NC_CONNECT_PENDING: NC_CONNECTED;
540 	}
541 	ha_ix++;
542     }
543 
544     /* Ran out. */
545     return NC_FAILED;
546 }
547 
548 /* There is data on the resolver pipe. */
549 static void
resolve_done(iosrc_t fd,ioid_t id)550 resolve_done(iosrc_t fd, ioid_t id)
551 {
552     int nr;
553     char slot_byte;
554     int slot;
555     int rv;
556     char *errmsg;
557     iosrc_t iosrc = INVALID_IOSRC;
558     net_connect_t nc;
559 
560     /* Read the data, which is the slot number. */
561     nr = read(resolver_pipe[0], &slot_byte, 1);
562     if (nr < 0) {
563 	popup_an_errno(errno, "Resolver pipe");
564 	return;
565     }
566     if (nr == 0) {
567 	popup_an_error("Resolver pipe EOF");
568     }
569 
570     /* Might be a canceled request. */
571     slot = (int)slot_byte;
572     if (slot != resolver_slot) {
573 	vtrace("Cleaning up canceled resolver slot %d\n", slot);
574 	cleanup_host_and_port(slot);
575 	return;
576     }
577 
578     rv = collect_host_and_port(slot, &haddr[0].sa, sizeof(haddr[0]), ha_len,
579 	    &current_port, &errmsg, NUM_HA, &num_ha);
580     if (RHP_IS_ERROR(rv)) {
581 	connect_error("%s", errmsg);
582 	return;
583     }
584     vtrace("Resolution complete, %d address%s\n", num_ha,
585 	    (num_ha == 1)? "": "es");
586 
587     /* Proceed with the connection. */
588     nc = finish_connect(&iosrc);
589     if (nc == NC_FAILED) {
590 	host_disconnect(true);
591     } else {
592 	host_continue_connect(iosrc, nc);
593     }
594 }
595 
596 /*
597  * net_connect
598  *	Establish a telnet socket to the given host passed as an argument.
599  *	Called only once and is responsible for setting up the telnet
600  *	variables.  Returns the file descriptor of the connected socket.
601  */
602 net_connect_t
net_connect(const char * host,char * portname,char * accept,bool ls,iosrc_t * iosrc)603 net_connect(const char *host, char *portname, char *accept, bool ls,
604 	iosrc_t *iosrc)
605 {
606     struct servent       *sp;
607     struct hostent       *hp;
608     char	       	passthru_haddr[8];
609     int			passthru_len = 0;
610     unsigned short	passthru_port = 0;
611     char		*errmsg;
612 
613     if (sizeof(state_name)/sizeof(state_name[0]) != NUM_CSTATE) {
614 	Error("telnet cstate_name has the wrong number of elements");
615     }
616 
617     *iosrc = INVALID_IOSRC;
618 
619     if (netrbuf == NULL) {
620 	netrbuf = (unsigned char *)Malloc(BUFSZ);
621     }
622 
623     linemode_init();
624     ns_brcvd = 0;
625     ns_rrcvd = 0;
626     ns_bsent = 0;
627     ns_rsent = 0;
628 
629     environ_init();
630 
631     environ_init();
632 
633     Replace(hostname, NewString(host));
634     net_accept = accept;
635 
636     starttls_pending = NOT_CONNECTED;
637     st_changed(ST_SECURE, false);
638 
639     /* set up temporary termtype */
640     net_set_default_termtype();
641 
642     /* get the passthru host and port number */
643     if (HOST_FLAG(PASSTHRU_HOST)) {
644 	const char *hn;
645 
646 	hn = getenv("INTERNET_HOST");
647 	if (hn == NULL) {
648 	    hn = "internet-gateway";
649 	}
650 
651 	hp = gethostbyname(hn);
652 	if (hp == (struct hostent *) 0) {
653 	    connect_error("Unknown passthru host: %s", hn);
654 	    return NC_FAILED;
655 	}
656 	memmove(passthru_haddr, hp->h_addr, hp->h_length);
657 	passthru_len = hp->h_length;
658 
659 	sp = getservbyname("telnet-passthru","tcp");
660 	if (sp != NULL) {
661 	    passthru_port = sp->s_port;
662 	} else {
663 	    passthru_port = htons(3514);
664 	}
665     } else if (appres.proxy != NULL) {
666 	proxytype_t pt;
667 	unsigned long lport;
668 	char *ptr;
669 	struct servent *sp;
670 
671 	pt = proxy_setup(appres.proxy, &proxy_user, &proxy_host,
672 		&proxy_portname);
673 	if (pt == PT_ERROR) {
674 	    return NC_FAILED;
675 	}
676 
677 	lport = strtoul(portname, &ptr, 0);
678 	if (ptr == portname || *ptr != '\0' || lport == 0L ||
679 		lport & ~0xffff) {
680 	    if (!(sp = getservbyname(portname, "tcp"))) {
681 		connect_error("Unknown port number or service: %s",
682 			portname);
683 		return NC_FAILED;
684 	    }
685 	    current_port = ntohs(sp->s_port);
686 	} else {
687 	    current_port = (unsigned short)lport;
688 	}
689 	proxy_type = pt;
690 	proxy_pending = true;
691     }
692 
693     /* fill in the socket address of the given host */
694     memset((char *) &haddr, 0, sizeof(haddr));
695     if (HOST_FLAG(PASSTHRU_HOST)) {
696 	/*
697 	 * XXX: We don't try multiple addresses for the passthru
698 	 * host.
699 	 */
700 	haddr[0].sin.sin_family = AF_INET;
701 	memmove(&haddr[0].sin.sin_addr, passthru_haddr, passthru_len);
702 	haddr[0].sin.sin_port = passthru_port;
703 	ha_len[0] = sizeof(struct sockaddr_in);
704 	num_ha = 1;
705 	ha_ix = 0;
706     } else if (proxy_pending) {
707 	/*
708 	 * XXX: We don't try multiple addresses for a proxy
709 	 * host.
710 	 */
711 	rhp_t rv;
712 	int nr;
713 
714 	rv = resolve_host_and_port(proxy_host, proxy_portname, &proxy_port,
715 		&haddr[0].sa, sizeof(haddr[0]), &ha_len[0], &errmsg, 1, &nr);
716 	if (RHP_IS_ERROR(rv)) {
717 	    connect_error("%s", errmsg);
718 	    return NC_FAILED;
719 	}
720 	num_ha = 1;
721 	ha_ix = 0;
722     } else {
723 #if defined(LOCAL_PROCESS) /*[*/
724 	if (ls) {
725 	    local_process = true;
726 	} else {
727 #endif /*]*/
728 	    rhp_t rv;
729 
730 	    if (resolver_pipe[0] == -1) {
731 		int rv;
732 
733 #if !defined(_WIN32) /*[*/
734 		rv = pipe(resolver_pipe);
735 #else /*][*/
736 		rv = _pipe(resolver_pipe, 512, _O_BINARY);
737 #endif /*]*/
738 		if (rv < 0) {
739 		    connect_error("resolver pipe: %s", strerror(errno));
740 		    return NC_FAILED;
741 		}
742 #if !defined(_WIN32) /*[*/
743 		AddInput(resolver_pipe[0], resolve_done);
744 #else /*][*/
745 		resolver_event = CreateEvent(NULL, FALSE, FALSE, NULL);
746 		AddInput(resolver_event, resolve_done);
747 #endif /*]*/
748 	    }
749 
750 #if defined(LOCAL_PROCESS) /*[*/
751 	    local_process = false;
752 #endif /*]*/
753 	    rv = resolve_host_and_port_a(host, portname, &current_port,
754 		    &haddr[0].sa, sizeof(haddr[0]), ha_len, &errmsg, NUM_HA,
755 		    &num_ha, &resolver_slot, resolver_pipe[1], resolver_event);
756 	    if (RHP_IS_ERROR(rv)) {
757 		connect_error("%s", errmsg);
758 		return NC_FAILED;
759 	    }
760 	    ha_ix = 0;
761 
762 	    if (rv == RHP_PENDING) {
763 		vtrace("Resolver slot is %d\n", resolver_slot);
764 		return NC_RESOLVING;
765 	    }
766 #if defined(LOCAL_PROCESS) /*[*/
767 	}
768 #endif /*]*/
769     }
770 
771 #if defined(LOCAL_PROCESS) /*[*/
772     if (local_process) {
773 	int amaster;
774 	struct winsize w;
775 
776 	w.ws_row = XMIT_ROWS;
777 	w.ws_col = XMIT_COLS;
778 	w.ws_xpixel = 0;
779 	w.ws_ypixel = 0;
780 
781 	switch (forkpty(&amaster, NULL, NULL, &w)) {
782 	case -1:	/* failed */
783 	    connect_errno(errno, "forkpty");
784 	    close_fail;
785 	case 0:	/* child */
786 	    putenv("TERM=xterm");
787 	    if (strchr(host, ' ') != NULL) {
788 		execlp("/bin/sh", "sh", "-c", host, NULL);
789 	    } else {
790 		char *arg1;
791 
792 		arg1 = strrchr(host, '/');
793 		execlp(host, (arg1 == NULL)? host: arg1 + 1, NULL);
794 	    }
795 	    perror(host);
796 	    _exit(1);
797 	    break;
798 	default:	/* parent */
799 	    sock = amaster;
800 	    fcntl(sock, F_SETFD, 1);
801 	    connection_complete();
802 	    host_in3270(linemode? CONNECTED_NVT: CONNECTED_NVT_CHAR);
803 	    host_set_flag(NO_TELNET_HOST);
804 	    break;
805 	}
806 	*iosrc = sock;
807 	return NC_CONNECTED;
808     }
809 #endif /*]*/
810 
811     return finish_connect(iosrc);
812 }
813 #undef close_fail
814 
815 /* Set up the LU list. */
816 static void
setup_lus(void)817 setup_lus(void)
818 {
819     char *lu;
820     char *comma;
821     int n_lus = 1;
822     int i;
823 
824     connected_lu = NULL;
825     connected_type = NULL;
826 
827     if (!luname[0]) {
828 	Replace(lus, NULL);
829 	curr_lu = NULL;
830 	try_lu = NULL;
831 	return;
832     }
833 
834     /*
835      * Count the commas in the LU name.  That plus one is the
836      * number of LUs to try.
837      */
838     lu = luname;
839     while ((comma = strchr(lu, ',')) != NULL) {
840 	n_lus++;
841 	lu++;
842     }
843 
844     /*
845      * Allocate enough memory to construct an argv[] array for
846      * the LUs.
847      */
848     Replace(lus,
849 	    (char **)Malloc((n_lus+1) * sizeof(char *) + strlen(luname) + 1));
850 
851     /* Copy each LU into the array. */
852     lu = (char *)(lus + n_lus + 1);
853     strcpy(lu, luname);
854     i = 0;
855     do {
856 	lus[i++] = lu;
857 	comma = strchr(lu, ',');
858 	if (comma != NULL) {
859 	    *comma = '\0';
860 	    lu = comma + 1;
861 	}
862     } while (comma != NULL);
863     lus[i] = NULL;
864     curr_lu = lus;
865     try_lu = *curr_lu;
866 }
867 
868 /* Send a periodic TELNET NOP. */
869 static void
send_nop(ioid_t id _is_unused)870 send_nop(ioid_t id _is_unused)
871 {
872     static unsigned char nop[] = { IAC, NOP };
873 
874     vtrace("SENT NOP\n");
875     net_rawout(nop, sizeof(nop));
876     if (cstate != NOT_CONNECTED) {
877 	nop_timeout_id = AddTimeOut(appres.nop_seconds * 1000, send_nop);
878     } else {
879 	nop_timeout_id = NULL_IOID;
880     }
881 }
882 
883 static void
net_connected_complete(void)884 net_connected_complete(void)
885 {
886     /* Done with TLS or proxy. */
887     if (appres.nvt_mode || HOST_FLAG(ANSI_HOST)) {
888 	host_in3270(CONNECTED_NVT);
889     } else {
890 	change_cstate(TELNET_PENDING, "net_connected_complete");
891     }
892     st_changed(ST_SECURE, false);
893 
894     /* set up telnet options */
895     memset((char *)myopts, 0, sizeof(myopts));
896     memset((char *)hisopts, 0, sizeof(hisopts));
897     did_ne_send = false;
898     deferred_will_ttype = false;
899     b8_zero(&e_funcs);
900     b8_set_bit(&e_funcs, TN3270E_FUNC_BIND_IMAGE);
901     b8_set_bit(&e_funcs, TN3270E_FUNC_RESPONSES);
902     b8_set_bit(&e_funcs, TN3270E_FUNC_SYSREQ);
903     e_xmit_seq = 0;
904     response_required = TN3270E_RSF_NO_RESPONSE;
905     need_tls_follows = false;
906     telnet_state = TNS_DATA;
907     ibptr = ibuf;
908 
909     /* clear statistics and flags */
910     time(&ns_time);
911     ns_brcvd = 0;
912     ns_rrcvd = 0;
913     ns_bsent = 0;
914     ns_rsent = 0;
915     syncing = 0;
916     tn3270e_negotiated = 0;
917     tn3270e_submode = E_UNBOUND;
918     tn3270e_bound = 0;
919 
920     setup_lus();
921 
922     check_linemode(true);
923 
924     /* write out the passthru hostname and port nubmer */
925     if (HOST_FLAG(PASSTHRU_HOST)) {
926 	char *buf;
927 
928 	buf = xs_buffer("%s %d\r\n", hostname, current_port);
929 	send(sock, buf, (int)strlen(buf), 0);
930 	Free(buf);
931     }
932 
933     /* set up NOP transmission */
934     if (appres.nop_seconds != 0) {
935 	nop_timeout_id = AddTimeOut(appres.nop_seconds * 1000, send_nop);
936     }
937 }
938 
939 static void
net_connected(void)940 net_connected(void)
941 {
942     bool data = false;
943 
944     /* Cancel the timeout. */
945     if (connect_timeout_id != NULL_IOID) {
946 	RemoveTimeOut(connect_timeout_id);
947 	connect_timeout_id = NULL_IOID;
948     }
949 
950     if (cstate != TLS_PENDING) {
951 	vtrace("Connected to %s, port %u.\n", hostname, current_port);
952     }
953 
954     if (proxy_pending) {
955 	proxy_negotiate_ret_t ret;
956 
957 	/* Don't do this again. */
958 	proxy_pending = false;
959 
960 	/* Negotiate with the proxy. */
961 	vtrace("Connected to proxy server %s, port %u.\n", proxy_host,
962 		proxy_port);
963 
964 	change_cstate(PROXY_PENDING, "net_connected");
965 
966 	ret = proxy_negotiate(sock, proxy_user, hostname, current_port, false);
967 	if (ret == PX_FAILURE) {
968 	    host_disconnect(true);
969 	    return;
970 	}
971 	if (ret == PX_WANTMORE) {
972 	    vtrace("Proxy needs more data\n");
973 	    return;
974 	}
975     }
976 
977     /* Set up TLS. */
978     if (HOST_FLAG(TLS_HOST) && sio != NULL && !secure_connection) {
979 	sio_negotiate_ret_t rv;
980 	char *session, *cert;
981 
982 	change_cstate(TLS_PENDING, "net_connected");
983 
984 	rv = sio_negotiate(sio, sock, hostname, &data);
985 	if (rv == SIG_FAILURE) {
986 	    /* No need to trace the error, it was already displayed. */
987 	    connect_error("%s", sio_last_error());
988 	    host_disconnect(true);
989 	    return;
990 	}
991 	if (rv == SIG_WANTMORE) {
992 	    vtrace("Need more TLS data\n");
993 	    return;
994 	}
995 
996 	secure_connection = true;
997 	session = indent_s(sio_session_info(sio));
998 	cert = indent_s(sio_server_cert_info(sio));
999 	vtrace("Connection is now secure.\n"
1000 		"Provider: %s\n"
1001 		"Session:\n%s\nServer certificate:\n%s\n",
1002 		sio_provider(), session, cert);
1003 	Free(session);
1004 	Free(cert);
1005 	st_changed(ST_SECURE, true);
1006 
1007 	/* Tell everyone else again. */
1008 	host_connected();
1009     }
1010 
1011     net_connected_complete();
1012 
1013     if (data) {
1014 	vtrace("Reading extra data after negotiation\n");
1015 	net_input(INVALID_IOSRC, NULL_IOID);
1016     }
1017 }
1018 
1019 /*
1020  * net_password_continue
1021  * 	Called by the password GUI when a password has been entered.
1022  */
1023 void
net_password_continue(const char * password)1024 net_password_continue(const char *password)
1025 {
1026     bool pending;
1027     iosrc_t s;
1028 
1029     if (!net_connect_pending) {
1030 	/* Connection is gone. */
1031 	return;
1032     }
1033     net_connect_pending = false;
1034 
1035     /* Try initializing sio again, with a new password. */
1036     if ((sio = sio_init_wrapper(password, HOST_FLAG(NO_VERIFY_CERT_HOST),
1037 		    net_accept, &pending)) == NULL) {
1038 	if (pending) {
1039 	    /* Still pending, try again. */
1040 	    net_connect_pending = true;
1041 	}
1042 	return;
1043     }
1044 
1045     /* Try connecting. */
1046     while (ha_ix < num_ha) {
1047 	s = connect_to(ha_ix, (ha_ix == num_ha - 1), &pending);
1048 	if (s != INVALID_IOSRC) {
1049 	    host_newfd(s);
1050 	    host_new_connection(pending);
1051 	    break;
1052 	}
1053 	ha_ix++;
1054     }
1055 }
1056 
1057 /*
1058  * remove_output
1059  * 	Cancel the callback for output available.
1060  */
1061 static void
remove_output(void)1062 remove_output(void)
1063 {
1064 #if !defined(_WIN32) /*[*/
1065     if (output_id != NULL_IOID) {
1066 	RemoveInput(output_id);
1067 	output_id = NULL_IOID;
1068     }
1069 #endif /*]*/
1070 }
1071 
1072 /*
1073  * connection_complete
1074  *	The connection appears to be complete (output is possible or input
1075  *	appeared ready but recv() returned EWOULDBLOCK).  Complete the
1076  *	connection-completion processing.
1077  */
1078 static void
connection_complete(void)1079 connection_complete(void)
1080 {
1081     host_connected();
1082     net_connected();
1083     remove_output();
1084 }
1085 
1086 #if !defined(_WIN32) /*[*/
1087 /*
1088  * output_possible
1089  *	Output is possible on the socket.  Used only when a connection is
1090  *	pending, to determine that the connection is complete.
1091  */
1092 static void
output_possible(iosrc_t fd _is_unused,ioid_t id _is_unused)1093 output_possible(iosrc_t fd _is_unused, ioid_t id _is_unused)
1094 {
1095 #if defined(CONNECT_GETPEERNAME) /*[*/
1096     sockaddr_46_t sa;
1097     socklen_t len = sizeof(sa);
1098 # define COMPLETE_CONNECT(s)	getpeername(s, &sa.sa, &len)
1099 # else /*][*/
1100 # define COMPLETE_CONNECT(s)	connect(s, &haddr[ha_ix].sa, sizeof(haddr[0]))
1101 #endif /*]*/
1102 
1103     vtrace("Output possible\n");
1104 
1105     /*
1106      * Try a connect() again to see if the connection completed sucessfully.
1107      * On some systems, such as Linux, this is harmless and succeeds.
1108      * On others, such as MacOS, this is mostly harmless and fails
1109      * with EISCONN.
1110      *
1111      * On Solaris, we do a getpeername() instead of a connect(). The second
1112      * connect() would fail with EINVAL there.
1113      */
1114     if (COMPLETE_CONNECT(sock) < 0) {
1115 	if (errno != EISCONN) {
1116 	    vtrace("RCVD socket error %d (%s)\n", socket_errno(),
1117 		    strerror(errno));
1118 	    popup_a_sockerr("Connection%s failed",
1119 		    proxy_pending? " to proxy server": "");
1120 	    host_disconnect(true);
1121 	    return;
1122 	}
1123     }
1124 
1125     if (cstate == TCP_PENDING) {
1126 	connection_complete();
1127     }
1128     remove_output();
1129 }
1130 #endif /*]*/
1131 
1132 
1133 /*
1134  * net_disconnect
1135  *	Shut down the socket.
1136  */
1137 void
net_disconnect(bool including_tls)1138 net_disconnect(bool including_tls)
1139 {
1140     if (including_tls && sio != NULL) {
1141 	sio_close(sio);
1142 	sio = NULL;
1143 	secure_connection = false;
1144 	st_changed(ST_SECURE, false);
1145     }
1146     if (CONNECTED) {
1147 	shutdown(sock, 2);
1148     }
1149     SOCK_CLOSE(sock);
1150     sock = INVALID_SOCKET;
1151 #if defined(_WIN32) /*[*/
1152     CloseHandle(sock_handle);
1153     sock_handle = INVALID_HANDLE_VALUE;
1154 #endif /*]*/
1155     vtrace("SENT disconnect\n");
1156 
1157     /* Cancel proxy. */
1158     if (proxy_type != PT_NONE) {
1159 	proxy_close();
1160 	proxy_type = PT_NONE;
1161 	proxy_pending = false;
1162     }
1163 
1164     /* Cancel the timeout. */
1165     if (connect_timeout_id != NULL_IOID) {
1166 	RemoveTimeOut(connect_timeout_id);
1167 	connect_timeout_id = NULL_IOID;
1168     }
1169 
1170     /* Cancel NOPs. */
1171     if (nop_timeout_id != NULL_IOID) {
1172 	RemoveTimeOut(nop_timeout_id);
1173 	nop_timeout_id = NULL_IOID;
1174     }
1175 
1176     /* We're not connected to an LU any more. */
1177     status_lu(NULL);
1178 
1179     /* We have no more interest in output buffer space. */
1180     remove_output();
1181 
1182     /* If we refused TLS and never entered 3270 mode, say so. */
1183     if (refused_tls && !any_host_data) {
1184 	if (!appres.tls.starttls) {
1185 	    connect_error("Connection failed:\n"
1186 		    "Host requested STARTTLS but STARTTLS disabled");
1187 	} else if (nested_tls) {
1188 	    connect_error("Connection failed:\n"
1189 		    "Host requested nested STARTTLS");
1190 	} else {
1191 	    connect_error("Connection failed:\n"
1192 		    "Host requested STARTTLS but TLS not supported");
1193 	}
1194     }
1195     refused_tls = false;
1196     nested_tls = false;
1197     any_host_data = false;
1198     starttls_pending = NOT_CONNECTED;
1199 
1200     net_connect_pending = false;
1201 
1202     change_cstate(NOT_CONNECTED, "net_disconnect");
1203 }
1204 
1205 /*
1206  * net_input
1207  *	Called by the toolkit whenever there is input available on the
1208  *	socket.  Reads the data, processes the special telnet commands
1209  *	and calls process_ds to process the 3270 data stream.
1210  */
1211 void
net_input(iosrc_t fd _is_unused,ioid_t id _is_unused)1212 net_input(iosrc_t fd _is_unused, ioid_t id _is_unused)
1213 {
1214     register unsigned char *cp;
1215     int	nr;
1216     bool ignore_tls = false;
1217 
1218 #if defined(_WIN32) /*[*/
1219     WSANETWORKEVENTS events;
1220 
1221     /*
1222      * Make the socket non-blocking.
1223      * Note that WSAEventSelect does this automatically (and won't allow
1224      * us to change it back to blocking), except on Wine.
1225      */
1226     if (sock != INVALID_SOCKET && non_blocking(true) < 0) {
1227 	host_disconnect(true);
1228 	return;
1229     }
1230 #endif /*]*/
1231     if (sock == INVALID_SOCKET) {
1232 	return;
1233     }
1234 
1235 #if defined(_WIN32) /*[*/
1236     if (WSAEnumNetworkEvents(sock, sock_handle, &events) != 0) {
1237 	popup_an_error("WSAEnumNetworkEvents failed: %s",
1238 		win32_strerror(WSAGetLastError()));
1239 	host_disconnect(true);
1240 	return;
1241     }
1242     vtrace("net_input: NetworkEvents 0x%lx%s%s%s\n",
1243 	    events.lNetworkEvents,
1244 	    (events.lNetworkEvents & FD_CONNECT) ? " CONNECT": "",
1245 	    (events.lNetworkEvents & FD_CLOSE) ? " CLOSE": "",
1246 	    (events.lNetworkEvents & FD_READ) ? " READ": "");
1247     if (cstate == TCP_PENDING) {
1248 	if (events.lNetworkEvents & FD_CONNECT) {
1249 	    if (events.iErrorCode[FD_CONNECT_BIT] != 0) {
1250 		connect_error("Connection%s failed: %s",
1251 			proxy_pending? " to proxy server": "",
1252 			win32_strerror(events.iErrorCode[FD_CONNECT_BIT]));
1253 		host_disconnect(true);
1254 		return;
1255 	    } else {
1256 		connection_complete();
1257 		if (sock == INVALID_SOCKET) {
1258 		    return;
1259 		}
1260 	    }
1261 	} else {
1262 	    vtrace("Spurious net_input call\n");
1263 	    return;
1264 	}
1265     }
1266 #endif /*]*/
1267 
1268     if (cstate == PROXY_PENDING) {
1269 	/* More proxy data available. */
1270 	proxy_negotiate_ret_t ret = proxy_continue();
1271 
1272 	if (ret == PX_WANTMORE) {
1273 	    vtrace("Proxy needs more data\n");
1274 	    return;
1275 	}
1276 	if (ret == PX_FAILURE) {
1277 	    host_disconnect(true);
1278 	    return;
1279 	}
1280 	net_connected_complete();
1281     }
1282 
1283     if (cstate == TLS_PENDING) {
1284 	/* More TLS data available. Process it. */
1285 	if (starttls_pending != NOT_CONNECTED) {
1286 	    net_starttls_continue();
1287 	} else {
1288 	    net_connected();
1289 	}
1290 	return;
1291     }
1292 
1293     if (HOST_FLAG(TLS_HOST) && sio != NULL && !secure_connection) {
1294 	/* Set up TLS tunnel after proxy connection. */
1295 	net_connected();
1296 	if (cstate == NOT_CONNECTED) {
1297 	    return;
1298 	}
1299     }
1300 
1301     nvt_data = 0;
1302 
1303     vtrace("Reading host socket%s\n", secure_connection? " via TLS": "");
1304 
1305     if (secure_connection) {
1306 	/*
1307 	 * OpenSSL does not like getting refused connections
1308 	 * when it hasn't done any I/O yet.  So peek ahead to
1309 	 * see if it's worth getting it involved at all.
1310 	 */
1311 	if (cstate == TLS_PENDING &&
1312 		(nr = recv(sock, (char *) netrbuf, 1, MSG_PEEK)) <= 0) {
1313 	    ignore_tls = true;
1314 	} else {
1315 	    nr = sio_read(sio, (char *) netrbuf, BUFSZ);
1316 	}
1317     } else {
1318 #if defined(LOCAL_PROCESS) /*[*/
1319 	if (local_process) {
1320 	    nr = read(sock, (char *) netrbuf, BUFSZ);
1321 	} else
1322 #endif /*]*/
1323 	{
1324 	    nr = recv(sock, (char *) netrbuf, BUFSZ, 0);
1325 	}
1326     }
1327     gettimeofday(&net_last_recv_ts, NULL);
1328     vtrace("Host socket read complete nr=%d\n", nr);
1329     if (nr < 0) {
1330 	if ((secure_connection && nr == SIO_EWOULDBLOCK) ||
1331 	    (!secure_connection && socket_errno() == SE_EWOULDBLOCK)) {
1332 	    vtrace("EWOULDBLOCK\n");
1333 	    return;
1334 	}
1335 	if (secure_connection && !ignore_tls) {
1336 	    connect_error("%s", sio_last_error());
1337 	    host_disconnect(true);
1338 	    return;
1339 	}
1340 	if (cstate == TCP_PENDING && socket_errno() == SE_EAGAIN) {
1341 	    connection_complete();
1342 	    return;
1343 	}
1344 #if defined(LOCAL_PROCESS) /*[*/
1345 	if (errno == EIO && local_process) {
1346 	    vtrace("RCVD local process disconnect\n");
1347 	    host_disconnect(false);
1348 	    return;
1349 	}
1350 #endif /*]*/
1351 	vtrace("RCVD socket error %d (%s)\n", socket_errno(),
1352 		socket_strerror(socket_errno()));
1353 	if (cstate == TCP_PENDING) {
1354 	    if (ha_ix == num_ha - 1) {
1355 		popup_a_sockerr(AnConnect "() to %s%s, port %d",
1356 			(proxy_type != PT_NONE)? "proxy ": "",
1357 			(proxy_type != PT_NONE)? proxy_host : hostname,
1358 			(proxy_type != PT_NONE)? proxy_port : current_port);
1359 	    } else {
1360 		bool pending;
1361 		iosrc_t s;
1362 
1363 		net_disconnect(false);
1364 		while (++ha_ix < num_ha) {
1365 		    s = connect_to(ha_ix, (ha_ix == num_ha - 1), &pending);
1366 		    if (s != INVALID_IOSRC) {
1367 			host_newfd(s);
1368 			host_new_connection(pending);
1369 			return;
1370 		    }
1371 		}
1372 	    }
1373 	} else if (socket_errno() != SE_ECONNRESET) {
1374 	    popup_a_sockerr("Socket read");
1375 	}
1376 	host_disconnect(true);
1377 	return;
1378     } else if (nr == 0) {
1379 	/* Host disconnected. */
1380 	vtrace("RCVD disconnect\n");
1381 	host_disconnect(false);
1382 	return;
1383     }
1384 
1385     /* Process the data. */
1386 
1387     if (cstate == TCP_PENDING) {
1388 	host_connected();
1389 	net_connected();
1390 	remove_output();
1391     }
1392 
1393     trace_netdata('<', netrbuf, nr);
1394 
1395     ns_brcvd += nr;
1396     stats_poke();
1397     for (cp = netrbuf; cp < (netrbuf + nr); cp++) {
1398 #if defined(LOCAL_PROCESS) /*[*/
1399 	if (local_process) {
1400 	    /* More to do here, probably. */
1401 	    if (cstate == TELNET_PENDING) {
1402 		host_in3270(linemode? CONNECTED_NVT: CONNECTED_NVT_CHAR);
1403 		hisopts[TELOPT_ECHO] = 1;
1404 		check_linemode(false);
1405 		kybdlock_clr(KL_AWAITING_FIRST, "telnet_fsm");
1406 		status_reset();
1407 		ps_process();
1408 	    }
1409 	    nvt_process((unsigned int) *cp);
1410 	} else {
1411 #endif /*]*/
1412 	    if (!telnet_fsm(*cp)) {
1413 		ctlr_dbcs_postprocess();
1414 		host_disconnect(true);
1415 		return;
1416 	    }
1417 #if defined(LOCAL_PROCESS) /*[*/
1418 	}
1419 #endif /*]*/
1420     }
1421 
1422     if (IN_NVT) {
1423 	ctlr_dbcs_postprocess();
1424     }
1425     net_nvt_break();
1426 
1427 #if defined(_WIN32) /*[*/
1428     if (events.lNetworkEvents & FD_CLOSE) {
1429 	vtrace("RCVD disconnect\n");
1430 	host_disconnect(false);
1431     }
1432 #endif /*]*/
1433 
1434     /* See if it's time to roll over the trace file. */
1435     trace_rollover_check();
1436 }
1437 
1438 /*
1439  * set16
1440  *	Put a 16-bit value in a buffer.
1441  *	Returns the number of bytes required.
1442  */
1443 static size_t
set16(char * buf,int n)1444 set16(char *buf, int n)
1445 {
1446     char *b0 = buf;
1447 
1448     n %= 256 * 256;
1449     if ((n / 256) == IAC) {
1450 	*(unsigned char *)buf++ = IAC;
1451     }
1452     *buf++ = (n / 256);
1453     n %= 256;
1454     if (n == IAC) {
1455 	*(unsigned char *)buf++ = IAC;
1456     }
1457     *buf++ = n;
1458     return buf - b0;
1459 }
1460 
1461 /*
1462  * send_naws
1463  *	Send a Telnet window size sub-option negotation.
1464  */
1465 static void
send_naws(void)1466 send_naws(void)
1467 {
1468     char naws_msg[14];
1469     size_t naws_len = 0;
1470 
1471     snprintf(naws_msg, sizeof(naws_msg), "%c%c%c", IAC, SB, TELOPT_NAWS);
1472     naws_len += 3;
1473     naws_len += set16(naws_msg + naws_len, XMIT_COLS);
1474     naws_len += set16(naws_msg + naws_len, XMIT_ROWS);
1475     sprintf(naws_msg + naws_len, "%c%c", IAC, SE);
1476     naws_len += 2;
1477     net_rawout((unsigned char *)naws_msg, naws_len);
1478     vtrace("SENT %s NAWS %d %d %s\n", cmd(SB), XMIT_COLS, XMIT_ROWS, cmd(SE));
1479 }
1480 
1481 
1482 /* Advance 'try_lu' to the next desired LU name. */
1483 static void
next_lu(void)1484 next_lu(void)
1485 {
1486     if (curr_lu != NULL && (try_lu = *++curr_lu) == NULL) {
1487 	curr_lu = NULL;
1488     }
1489 }
1490 
1491 #if defined(EBCDIC_HOST) /*[*/
1492 /*
1493  * force_ascii
1494  * 	Force the argument string to ASCII.  On ASCII (or ASCII-derived) hosts,
1495  * 	this is a no-op.  On EBCDIC-based hosts, translation is necessary.
1496  */
1497 static const char *
force_ascii(const char * s)1498 force_ascii(const char *s)
1499 {
1500     static char buf[256];
1501     unsigned char c, e;
1502     int i;
1503 
1504     i = 0;
1505     while ((c = *s++) && i < sizeof(buf) - 1) {
1506 	e = ebc2asc0[c];
1507 	if (e) {
1508 	    buf[i++] = e;
1509 	} else {
1510 	    buf[i++] = 0x3f; /* '?' */
1511 	}
1512     }
1513     buf[i] = '\0';
1514     return buf;
1515 }
1516 #else /*][*/
1517 #define force_ascii(s) (s)
1518 #endif /*]*/
1519 
1520 #if defined(EBCDIC_HOST) /*[*/
1521 /*
1522  * force_local
1523  * 	Force the argument string from ASCII to the local character set.  On
1524  * 	ASCII (or ASCII-derived) hosts, this is a no-op.  On EBCDIC-based
1525  * 	hosts, translation is necessary.
1526  *
1527  * 	Does the translation in-place.
1528  */
1529 void
force_local(char * s)1530 force_local(char *s)
1531 {
1532     unsigned char c, e;
1533 
1534     while ((c = *s) != '\0') {
1535 	e = asc2ebc0[c];
1536 	if (e) {
1537 	    *s = e;
1538 	} else {
1539 	    *s = '?';
1540 	}
1541 	s++;
1542     }
1543 }
1544 #else /*][*/
1545 #define force_local(s)
1546 #endif /*]*/
1547 
1548 /*
1549  * telnet_fsm
1550  *	Telnet finite-state machine.
1551  *	Returns true for okay, false for errors.
1552  */
1553 static bool
telnet_fsm(unsigned char c)1554 telnet_fsm(unsigned char c)
1555 {
1556     char *see_chr;
1557     size_t sl;
1558 
1559     switch (telnet_state) {
1560     case TNS_DATA:	/* normal data processing */
1561 	if (!HOST_FLAG(NO_TELNET_HOST) && c == IAC) {
1562 	    /* got a telnet command */
1563 	    telnet_state = TNS_IAC;
1564 	    net_nvt_break();
1565 	    break;
1566 	}
1567 	if (cstate == TELNET_PENDING) {
1568 	    /* now can assume NVT mode */
1569 	    if (linemode) {
1570 		linemode_buf_init();
1571 	    }
1572 	    host_in3270(linemode? CONNECTED_NVT: CONNECTED_NVT_CHAR);
1573 	    kybdlock_clr(KL_AWAITING_FIRST, "telnet_fsm");
1574 	    status_reset();
1575 	    ps_process();
1576 	}
1577 	if (IN_NVT && !IN_E) {
1578 	    if (!nvt_data) {
1579 		vtrace("<.. ");
1580 		nvt_data = 4;
1581 	    }
1582 	    see_chr = ctl_see((int) c);
1583 	    nvt_data += (sl = strlen(see_chr));
1584 	    if (nvt_data >= TRACELINE) {
1585 		vtrace(" ...\n... ");
1586 		nvt_data = 4 + sl;
1587 	    }
1588 	    vtrace("%s", see_chr);
1589 	    if (!syncing) {
1590 		if (linemode && appres.linemode.onlcr && c == '\n') {
1591 		    nvt_process((unsigned int) '\r');
1592 		}
1593 		nvt_process((unsigned int) c);
1594 	    }
1595 	} else {
1596 	    store3270in(c);
1597 	}
1598 	break;
1599     case TNS_IAC:	/* process a telnet command */
1600 	if (c != EOR && c != IAC) {
1601 	    vtrace("RCVD %s ", cmd(c));
1602 	}
1603 	switch (c) {
1604 	case IAC:	/* escaped IAC, insert it */
1605 	    if (IN_NVT && !IN_E) {
1606 		if (!nvt_data) {
1607 		    vtrace("<.. ");
1608 		    nvt_data = 4;
1609 		}
1610 		see_chr = ctl_see((int) c);
1611 		nvt_data += (sl = strlen(see_chr));
1612 		if (nvt_data >= TRACELINE) {
1613 		    vtrace(" ...\n ...");
1614 		    nvt_data = 4 + sl;
1615 		}
1616 		vtrace("%s", see_chr);
1617 		nvt_process((unsigned int) c);
1618 	    } else {
1619 		store3270in(c);
1620 	    }
1621 	    telnet_state = TNS_DATA;
1622 	    break;
1623 	case EOR:	/* eor, process accumulated input */
1624 	    if (IN_3270 || (IN_E && tn3270e_negotiated)) {
1625 		ns_rrcvd++;
1626 		stats_poke();
1627 		if (process_eor()) {
1628 		    return false;
1629 		}
1630 	    } else {
1631 		Warning("EOR received when not in 3270 mode, ignored.");
1632 	    }
1633 	    vtrace("RCVD EOR\n");
1634 	    ibptr = ibuf;
1635 	    telnet_state = TNS_DATA;
1636 	    break;
1637 	case WILL:
1638 	    telnet_state = TNS_WILL;
1639 	    break;
1640 	case WONT:
1641 	    telnet_state = TNS_WONT;
1642 	    break;
1643 	case DO:
1644 	    telnet_state = TNS_DO;
1645 	    break;
1646 	case DONT:
1647 	    telnet_state = TNS_DONT;
1648 	    break;
1649 	case SB:
1650 	    telnet_state = TNS_SB;
1651 	    if (sbbuf == NULL) {
1652 		sbbuf = (unsigned char *)Malloc(1024);
1653 	    }
1654 	    sbptr = sbbuf;
1655 	    break;
1656 	case DM:
1657 	    vtrace("\n");
1658 	    if (syncing) {
1659 		syncing = 0;
1660 #if !defined(_WIN32) /*[*/
1661 		x_except_on(sock);
1662 #else /*][*/
1663 		x_except_on(sock_handle);
1664 #endif /*]*/
1665 	    }
1666 	    telnet_state = TNS_DATA;
1667 	    break;
1668 	case GA:
1669 	case NOP:
1670 	    vtrace("\n");
1671 	    telnet_state = TNS_DATA;
1672 	    break;
1673 	default:
1674 	    vtrace("???\n");
1675 	    telnet_state = TNS_DATA;
1676 	    break;
1677 	}
1678 	break;
1679     case TNS_WILL:	/* telnet WILL DO OPTION command */
1680 	vtrace("%s\n", opt(c));
1681 	switch (c) {
1682 	case TELOPT_SGA:
1683 	case TELOPT_BINARY:
1684 	case TELOPT_EOR:
1685 	case TELOPT_TTYPE:
1686 	case TELOPT_ECHO:
1687 	case TELOPT_TN3270E:
1688 	    if (c != TELOPT_TN3270E || !HOST_FLAG(NON_TN3270E_HOST)) {
1689 		if (!hisopts[c]) {
1690 		    hisopts[c] = 1;
1691 		    do_opt[2] = c;
1692 		    net_rawout(do_opt, sizeof(do_opt));
1693 		    vtrace("SENT %s %s\n", cmd(DO), opt(c));
1694 
1695 		    /* For UTS, volunteer to do EOR when they do. */
1696 		    if (c == TELOPT_EOR && !myopts[c]) {
1697 			myopts[c] = 1;
1698 			will_opt[2] = c;
1699 			net_rawout(will_opt, sizeof(will_opt));
1700 			vtrace("SENT %s %s\n", cmd(WILL), opt(c));
1701 		    }
1702 
1703 		    check_in3270();
1704 		    check_linemode(false);
1705 		}
1706 		break;
1707 	    }
1708 	default:
1709 	    dont_opt[2] = c;
1710 	    net_rawout(dont_opt, sizeof(dont_opt));
1711 	    vtrace("SENT %s %s\n", cmd(DONT), opt(c));
1712 	    break;
1713 	}
1714 	telnet_state = TNS_DATA;
1715 	break;
1716     case TNS_WONT:	/* telnet WONT DO OPTION command */
1717 	vtrace("%s\n", opt(c));
1718 	if (hisopts[c]) {
1719 	    hisopts[c] = 0;
1720 	    dont_opt[2] = c;
1721 	    net_rawout(dont_opt, sizeof(dont_opt));
1722 	    vtrace("SENT %s %s\n", cmd(DONT), opt(c));
1723 	    check_in3270();
1724 	    check_linemode(false);
1725 	}
1726 	telnet_state = TNS_DATA;
1727 	break;
1728     case TNS_DO:	/* telnet PLEASE DO OPTION command */
1729 	vtrace("%s\n", opt(c));
1730 	switch (c) {
1731 	case TELOPT_BINARY:
1732 	case TELOPT_EOR:
1733 	case TELOPT_TTYPE:
1734 	case TELOPT_SGA:
1735 	case TELOPT_NAWS:
1736 	case TELOPT_TM:
1737 	case TELOPT_TN3270E:
1738 	case TELOPT_STARTTLS:
1739 	    if (c == TELOPT_STARTTLS &&
1740 		    (!sio_supported() ||
1741 		     !appres.tls.starttls ||
1742 		     secure_connection)) {
1743 		refused_tls = true;
1744 		if (secure_connection) {
1745 		    nested_tls = true;
1746 		}
1747 		goto wont;
1748 	    }
1749 	case TELOPT_NEW_ENVIRON:
1750 	    if (c == TELOPT_TN3270E && HOST_FLAG(NON_TN3270E_HOST)) {
1751 		goto wont;
1752 	    }
1753 	    if (c == TELOPT_TM && !appres.bsd_tm) {
1754 		goto wont;
1755 	    }
1756 	    if (c == TELOPT_NEW_ENVIRON && !appres.new_environ) {
1757 		goto wont;
1758 	    }
1759 	    if (c == TELOPT_TTYPE && myopts[TELOPT_NEW_ENVIRON] &&
1760 		    !did_ne_send) {
1761 		/*
1762 		 * Defer sending WILL TTYPE until after the host asks for SB
1763 		 * NEW_ENVIRON SEND.
1764 		 */
1765 		myopts[c] = 1;
1766 		deferred_will_ttype = true;
1767 		break;
1768 	    }
1769 
1770 	    if (!myopts[c]) {
1771 		if (c != TELOPT_TM) {
1772 		    myopts[c] = 1;
1773 		}
1774 		will_opt[2] = c;
1775 		net_rawout(will_opt, sizeof(will_opt));
1776 		vtrace("SENT %s %s\n", cmd(WILL), opt(c));
1777 		check_in3270();
1778 		check_linemode(false);
1779 	    }
1780 	    if (c == TELOPT_NAWS) {
1781 		send_naws();
1782 	    }
1783 	    if (c == TELOPT_STARTTLS) {
1784 		static unsigned char follows_msg[] = {
1785 		    IAC, SB, TELOPT_STARTTLS, TLS_FOLLOWS, IAC, SE
1786 		};
1787 
1788 		/*
1789 		 * Send IAC SB STARTTLS FOLLOWS IAC SE to announce that what
1790 		 * follows is TLS.
1791 		 */
1792 		net_rawout(follows_msg, sizeof(follows_msg));
1793 		vtrace("SENT %s %s FOLLOWS %s\n", cmd(SB),
1794 			opt(TELOPT_STARTTLS), cmd(SE));
1795 		need_tls_follows = true;
1796 	    }
1797 	    break;
1798 	default:
1799 	wont:
1800 	    wont_opt[2] = c;
1801 	    net_rawout(wont_opt, sizeof(wont_opt));
1802 	    vtrace("SENT %s %s\n", cmd(WONT), opt(c));
1803 	    break;
1804 	}
1805 	telnet_state = TNS_DATA;
1806 	break;
1807     case TNS_DONT:	/* telnet PLEASE DON'T DO OPTION command */
1808 	vtrace("%s\n", opt(c));
1809 	if (myopts[c]) {
1810 	    myopts[c] = 0;
1811 	    wont_opt[2] = c;
1812 	    net_rawout(wont_opt, sizeof(wont_opt));
1813 	    vtrace("SENT %s %s\n", cmd(WONT), opt(c));
1814 	    check_in3270();
1815 	    check_linemode(false);
1816 	}
1817 	if (c == TELOPT_TTYPE && deferred_will_ttype) {
1818 	    deferred_will_ttype = false;
1819 	}
1820 	telnet_state = TNS_DATA;
1821 	break;
1822     case TNS_SB:	/* telnet sub-option string command */
1823 	if (c == IAC) {
1824 	    telnet_state = TNS_SB_IAC;
1825 	} else {
1826 	    *sbptr++ = c;
1827 	}
1828 	break;
1829     case TNS_SB_IAC:	/* telnet sub-option string command */
1830 	*sbptr++ = c;
1831 	if (c == SE) {
1832 	    telnet_state = TNS_DATA;
1833 	    if (sbbuf[0] == TELOPT_TTYPE && sbbuf[1] == TELQUAL_SEND) {
1834 		size_t tt_len, tb_len;
1835 		char *tt_out;
1836 
1837 		vtrace("%s %s\n", opt(sbbuf[0]), telquals[sbbuf[1]]);
1838 		if (lus != NULL && try_lu == NULL) {
1839 		    /* None of the LUs worked. */
1840 		    connect_error("Cannot connect to specified LU");
1841 		    return false;
1842 		}
1843 
1844 		tt_len = strlen(termtype);
1845 		if (try_lu != NULL && *try_lu) {
1846 		    tt_len += strlen(try_lu) + 1;
1847 		    connected_lu = try_lu;
1848 		} else {
1849 		    connected_lu = NULL;
1850 		}
1851 
1852 		tb_len = 4 + tt_len + 2;
1853 		tt_out = Malloc(tb_len + 1);
1854 		sprintf(tt_out, "%c%c%c%c%s%s%s%c%c",
1855 			IAC, SB, TELOPT_TTYPE, TELQUAL_IS,
1856 			force_ascii(termtype),
1857 			(try_lu != NULL && *try_lu)? "@": "",
1858 			(try_lu != NULL && *try_lu)?  force_ascii(try_lu) : "",
1859 			IAC, SE);
1860 		net_hexnvt_out_framed((unsigned char *)tt_out, tb_len, true);
1861 		Free(tt_out);
1862 
1863 		status_lu(connected_lu);
1864 
1865 		vtrace("SENT %s %s %s %s%s%s %s\n", cmd(SB), opt(TELOPT_TTYPE),
1866 			telquals[TELQUAL_IS], termtype,
1867 			(try_lu != NULL && *try_lu)? "@": "",
1868 			(try_lu != NULL && *try_lu)? try_lu: "",
1869 			cmd(SE));
1870 
1871 		/* Advance to the next LU name. */
1872 		next_lu();
1873 	    } else if (myopts[TELOPT_TN3270E] && sbbuf[0] == TELOPT_TN3270E) {
1874 		if (tn3270e_negotiate()) {
1875 		    return false;
1876 		}
1877 	    } else if (sio_supported() &&
1878 		    sio != NULL &&
1879 		    need_tls_follows &&
1880 		    myopts[TELOPT_STARTTLS] &&
1881 		    sbbuf[0] == TELOPT_STARTTLS) {
1882 		continue_tls(sbbuf, (int)(sbptr - sbbuf));
1883 	    } else if (sbbuf[0] == TELOPT_NEW_ENVIRON &&
1884 		    sbbuf[1] == TELQUAL_SEND && appres.new_environ) {
1885 		unsigned char *reply_buf;
1886 		size_t reply_buflen;
1887 		char *trace_in;
1888 		char *trace_out;
1889 
1890 		if (!telnet_new_environ(sbbuf + 2, (sbptr - sbbuf - 3),
1891 			    &reply_buf, &reply_buflen, &trace_in,
1892 			    &trace_out)) {
1893 		    vtrace("%s %s [error]\n", opt(sbbuf[0]),
1894 			    telquals[sbbuf[1]]);
1895 		} else {
1896 		    vtrace("%s\n", trace_in);
1897 		    Free(trace_in);
1898 		    net_rawout(reply_buf, reply_buflen);
1899 		    Free(reply_buf);
1900 		    vtrace("SENT %s\n", trace_out);
1901 		    Free(trace_out);
1902 		}
1903 
1904 		/*
1905 		 * Remember that we did a NEW_ENVIRON SEND, so we won't defer a
1906 		 * future DO TTYPE.
1907 		 */
1908 		did_ne_send = true;
1909 
1910 		/* Now respond to DO TTYPE. */
1911 		if (deferred_will_ttype && myopts[TELOPT_TTYPE]) {
1912 		    will_opt[2] = TELOPT_TTYPE;
1913 		    net_rawout(will_opt, sizeof(will_opt));
1914 		    vtrace("SENT %s %s\n", cmd(WILL), opt(TELOPT_TTYPE));
1915 		    check_in3270();
1916 		    check_linemode(false);
1917 		    deferred_will_ttype = false;
1918 		}
1919 	    }
1920 
1921 	} else {
1922 	    telnet_state = TNS_SB;
1923 	}
1924 	break;
1925     }
1926     return true;
1927 }
1928 
1929 /* Send a TN3270E terminal type request. */
1930 static void
tn3270e_request(void)1931 tn3270e_request(void)
1932 {
1933     size_t tt_len, tb_len;
1934     char *tt_out;
1935     char *t;
1936     char *xtn;
1937 
1938     /* Convert 3279 to 3278, per the RFC. */
1939     xtn = NewString(termtype);
1940     if (!strncmp(xtn, "IBM-3279", 8)) {
1941 	xtn[7] = '8';
1942     }
1943 
1944     tt_len = strlen(termtype);
1945     if (try_lu != NULL && *try_lu) {
1946 	tt_len += strlen(try_lu) + 1;
1947     }
1948 
1949     tb_len = 5 + tt_len + 2;
1950     tt_out = Malloc(tb_len + 1);
1951     t = tt_out;
1952     t += sprintf(tt_out, "%c%c%c%c%c%s",
1953 	IAC, SB, TELOPT_TN3270E, TN3270E_OP_DEVICE_TYPE, TN3270E_OP_REQUEST,
1954 	force_ascii(xtn));
1955 
1956     if (try_lu != NULL && *try_lu) {
1957 	t += sprintf(t, "%c%s", TN3270E_OP_CONNECT, force_ascii(try_lu));
1958     }
1959 
1960     sprintf(t, "%c%c", IAC, SE);
1961 
1962     net_hexnvt_out_framed((unsigned char *)tt_out, tb_len, true);
1963     Free(tt_out);
1964 
1965     vtrace("SENT %s %s DEVICE-TYPE REQUEST %s%s%s %s\n",
1966 	cmd(SB), opt(TELOPT_TN3270E), xtn,
1967 	(try_lu != NULL && *try_lu)? " CONNECT ": "",
1968 	(try_lu != NULL && *try_lu)? try_lu: "",
1969 	cmd(SE));
1970 
1971     Free(xtn);
1972 }
1973 
1974 /*
1975  * Back off of TN3270E.
1976  */
1977 static void
backoff_tn3270e(const char * why)1978 backoff_tn3270e(const char *why)
1979 {
1980     vtrace("Aborting TN3270E: %s\n", why);
1981 
1982     /* Tell the host 'no'. */
1983     wont_opt[2] = TELOPT_TN3270E;
1984     net_rawout(wont_opt, sizeof(wont_opt));
1985     vtrace("SENT %s %s\n", cmd(WONT), opt(TELOPT_TN3270E));
1986 
1987     /* Restore the LU list; we may need to run it again in TN3270 mode. */
1988     setup_lus();
1989 
1990     /* Reset our internal state. */
1991     myopts[TELOPT_TN3270E] = 0;
1992     check_in3270();
1993 }
1994 
1995 /*
1996  * Negotiation of TN3270E options.
1997  * Returns 0 if okay, -1 if we have to give up altogether.
1998  */
1999 static int
tn3270e_negotiate(void)2000 tn3270e_negotiate(void)
2001 {
2002 #define LU_MAX	32
2003     static char reported_lu[LU_MAX+1];
2004     static char reported_type[LU_MAX+1];
2005     int sblen;
2006     b8_t e_rcvd;
2007 
2008     /* Find out how long the subnegotiation buffer is. */
2009     for (sblen = 0; ; sblen++) {
2010 	if (sbbuf[sblen] == SE) {
2011 	    break;
2012 	}
2013     }
2014 
2015     vtrace("TN3270E ");
2016 
2017     switch (sbbuf[1]) {
2018     case TN3270E_OP_SEND:
2019 	if (sbbuf[2] == TN3270E_OP_DEVICE_TYPE) {
2020 	    /* Host wants us to send our device type. */
2021 	    vtrace("SEND DEVICE-TYPE SE\n");
2022 	    tn3270e_request();
2023 	} else {
2024 	    vtrace("SEND ??%u SE\n", sbbuf[2]);
2025 	}
2026 	break;
2027 
2028     case TN3270E_OP_DEVICE_TYPE:
2029 	/* Device type negotiation. */
2030 	vtrace("DEVICE-TYPE ");
2031 	switch (sbbuf[2]) {
2032 	case TN3270E_OP_IS: {
2033 	    int tnlen, snlen;
2034 
2035 	    /* Device type success. */
2036 
2037 	    /* Isolate the terminal type and session. */
2038 	    tnlen = 0;
2039 	    while (sbbuf[3+tnlen] != SE &&
2040 		   sbbuf[3+tnlen] != TN3270E_OP_CONNECT) {
2041 		tnlen++;
2042 	    }
2043 	    snlen = 0;
2044 	    if (sbbuf[3+tnlen] == TN3270E_OP_CONNECT) {
2045 		while(sbbuf[3+tnlen+1+snlen] != SE) {
2046 		    snlen++;
2047 		}
2048 	    }
2049 
2050 	    /* Remember the LU. */
2051 	    if (tnlen) {
2052 		if (tnlen > LU_MAX) {
2053 		    tnlen = LU_MAX;
2054 		}
2055 		strncpy(reported_type, (char *)&sbbuf[3], tnlen);
2056 		reported_type[tnlen] = '\0';
2057 		force_local(reported_type);
2058 		connected_type = reported_type;
2059 	    }
2060 	    if (snlen) {
2061 		if (snlen > LU_MAX) {
2062 		    snlen = LU_MAX;
2063 		}
2064 		strncpy(reported_lu, (char *)&sbbuf[3+tnlen+1], snlen);
2065 		reported_lu[snlen] = '\0';
2066 		force_local(reported_lu);
2067 		connected_lu = reported_lu;
2068 	    }
2069 
2070 	    vtrace("IS %s CONNECT %s SE\n", tnlen? connected_type: "",
2071 		    snlen? connected_lu: "");
2072 
2073 	    if (snlen) {
2074 		status_lu(connected_lu);
2075 	    }
2076 
2077 	    /* Tell them what we can do. */
2078 	    tn3270e_subneg_send(TN3270E_OP_REQUEST, &e_funcs);
2079 	    break;
2080 	    }
2081 	case TN3270E_OP_REJECT:
2082 	    /* Device type failure. */
2083 	    vtrace("REJECT REASON %s SE\n", rsn(sbbuf[4]));
2084 	    if (sbbuf[4] == TN3270E_REASON_UNSUPPORTED_REQ) {
2085 		backoff_tn3270e("Host rejected request type");
2086 		break;
2087 	    }
2088 
2089 	    next_lu();
2090 	    if (try_lu != NULL) {
2091 		/* Try the next LU. */
2092 		tn3270e_request();
2093 	    } else if (lus != NULL) {
2094 		/* No more LUs to try.  Give up. */
2095 		backoff_tn3270e("Host rejected resource(s)");
2096 	    } else {
2097 		backoff_tn3270e("Device type rejected");
2098 	    }
2099 
2100 	    break;
2101 	default:
2102 	    vtrace("??%u SE\n", sbbuf[2]);
2103 	    break;
2104 	}
2105 	break;
2106 
2107     case TN3270E_OP_FUNCTIONS:
2108 	/* Functions negotiation. */
2109 	vtrace("FUNCTIONS ");
2110 
2111 	switch (sbbuf[2]) {
2112 	case TN3270E_OP_REQUEST:
2113 	    /* Host is telling us what functions they want. */
2114 	    vtrace("REQUEST %s SE\n",
2115 		    tn3270e_function_names(sbbuf+3, sblen-3));
2116 
2117 	    tn3270e_fdecode(sbbuf+3, sblen-3, &e_rcvd);
2118 	    if (b8_none_added(&e_funcs, &e_rcvd)) {
2119 		/* They want what we want, or less.  Done. */
2120 		b8_copy(&e_funcs, &e_rcvd);
2121 		tn3270e_subneg_send(TN3270E_OP_IS, &e_funcs);
2122 		tn3270e_negotiated = 1;
2123 		vtrace("TN3270E option negotiation complete.\n");
2124 		check_in3270();
2125 	    } else {
2126 		/*
2127 		 * They want us to do something we can't.
2128 		 * Request the common subset.
2129 		 */
2130 		b8_and(&e_funcs, &e_funcs, &e_rcvd);
2131 		tn3270e_subneg_send(TN3270E_OP_REQUEST, &e_funcs);
2132 	    }
2133 	    break;
2134 
2135 	case TN3270E_OP_IS:
2136 	    /* They accept our last request, or a subset thereof. */
2137 	    vtrace("IS %s SE\n", tn3270e_function_names(sbbuf+3, sblen-3));
2138 	    tn3270e_fdecode(sbbuf+3, sblen-3, &e_rcvd);
2139 	    if (b8_none_added(&e_funcs, &e_rcvd)) {
2140 		/* They want what we want, or less.  Done. */
2141 		b8_copy(&e_funcs, &e_rcvd);
2142 	    } else {
2143 		/*
2144 		 * They've added something. Abandon TN3270E,
2145 		 * they're brain dead.
2146 		 */
2147 		backoff_tn3270e("Host illegally added function(s)");
2148 		break;
2149 	    }
2150 	    tn3270e_negotiated = 1;
2151 	    vtrace("TN3270E option negotiation complete.\n");
2152 
2153 	    /*
2154 	     * If the host does not support BIND_IMAGE, then we
2155 	     * must go straight to 3270 mode. We do not implicitly
2156 	     * unlock the keyboard, though -- that requires a
2157 	     * Write command from the host.
2158 	     */
2159 	    if (!b8_bit_is_set(&e_funcs, TN3270E_FUNC_BIND_IMAGE)) {
2160 		tn3270e_submode = E_3270;
2161 	    }
2162 
2163 	    check_in3270();
2164 	    break;
2165 
2166 	default:
2167 	    vtrace("??%u SE\n", sbbuf[2]);
2168 	    break;
2169 	}
2170 	break;
2171 
2172     default:
2173 	vtrace("??%u SE\n", sbbuf[1]);
2174     }
2175 
2176     /* Good enough for now. */
2177     return 0;
2178 }
2179 
2180 /* Expand a string of TN3270E function codes into text. */
2181 static const char *
tn3270e_function_names(const unsigned char * buf,int len)2182 tn3270e_function_names(const unsigned char *buf, int len)
2183 {
2184     int i;
2185     static char text_buf[1024];
2186     char *s = text_buf;
2187 
2188     if (!len) {
2189 	return("(null)");
2190     }
2191     for (i = 0; i < len; i++) {
2192 	s += sprintf(s, "%s%s", (s == text_buf)? "": " ", fnn(buf[i]));
2193     }
2194     return text_buf;
2195 }
2196 
2197 /* Expand the current TN3270E function codes into text. */
2198 const char *
tn3270e_current_opts(void)2199 tn3270e_current_opts(void)
2200 {
2201     int i;
2202     static char text_buf[1024];
2203     char *s = text_buf;
2204 
2205     if (b8_is_zero(&e_funcs) || !IN_E) {
2206 	return NULL;
2207     }
2208     for (i = 0; i < MX8; i++) {
2209 	if (b8_bit_is_set(&e_funcs, i)) {
2210 	    s += sprintf(s, "%s%s", (s == text_buf)? "": " ", fnn(i));
2211 	}
2212     }
2213     return text_buf;
2214 }
2215 
2216 /* Transmit a TN3270E FUNCTIONS REQUEST or FUNCTIONS IS message. */
2217 static void
tn3270e_subneg_send(unsigned char op,b8_t * funcs)2218 tn3270e_subneg_send(unsigned char op, b8_t *funcs)
2219 {
2220     unsigned char proto_buf[7 + MX8];
2221     int proto_len;
2222     int i;
2223 
2224     /* Construct the buffers. */
2225     memcpy(proto_buf, functions_req, 4);
2226     proto_buf[4] = op;
2227     proto_len = 5;
2228     for (i = 0; i < MX8; i++) {
2229 	if (b8_bit_is_set(funcs, (i))) {
2230 	    proto_buf[proto_len++] = i;
2231 	}
2232     }
2233 
2234     /* Complete and send out the protocol message. */
2235     proto_buf[proto_len++] = IAC;
2236     proto_buf[proto_len++] = SE;
2237     net_rawout(proto_buf, proto_len);
2238 
2239     /* Complete and send out the trace text. */
2240     vtrace("SENT %s %s FUNCTIONS %s %s %s\n",
2241 	    cmd(SB), opt(TELOPT_TN3270E),
2242 	    (op == TN3270E_OP_REQUEST)? "REQUEST": "IS",
2243 	    tn3270e_function_names(proto_buf + 5, proto_len - 7),
2244 	    cmd(SE));
2245 }
2246 
2247 /* Translate a string of TN3270E functions into a bitmap. */
2248 static void
tn3270e_fdecode(const unsigned char * buf,int len,b8_t * r)2249 tn3270e_fdecode(const unsigned char *buf, int len, b8_t *r)
2250 {
2251     int i;
2252 
2253     b8_zero(r);
2254     for (i = 0; i < len; i++) {
2255 	b8_set_bit(r, buf[i]);
2256     }
2257 }
2258 
2259 static int
maxru(unsigned char c)2260 maxru(unsigned char c)
2261 {
2262     if (!(c & 0x80)) {
2263 	return 0;
2264     }
2265     return ((c >> 4) & 0x0f) * (1 << (c & 0xf));
2266 }
2267 
2268 static void
process_bind(unsigned char * buf,size_t buflen)2269 process_bind(unsigned char *buf, size_t buflen)
2270 {
2271     size_t namelen;
2272     size_t dest_ix = 0;
2273 
2274     /* Save the raw image. */
2275     Replace(bind_image, (unsigned char *)Malloc(buflen));
2276     memcpy(bind_image, buf, buflen);
2277     bind_image_len = buflen;
2278 
2279     /* Clean up the derived state. */
2280     if (plu_name == NULL) {
2281 	plu_name = Malloc(mb_max_len(BIND_PLU_NAME_MAX + 1));
2282     }
2283     memset(plu_name, '\0', mb_max_len(BIND_PLU_NAME_MAX + 1));
2284     maxru_sec = 0;
2285     maxru_pri = 0;
2286     bind_rd = 0;
2287     bind_cd = 0;
2288     bind_ra = 0;
2289     bind_ca = 0;
2290     bind_state = 0;
2291 
2292     /* Make sure it's a BIND. */
2293     if (buflen < 1 || buf[0] != BIND_RU) {
2294 	return;
2295     }
2296 
2297     /* Extract the maximum RUs. */
2298     if (buflen > BIND_OFF_MAXRU_SEC) {
2299 	maxru_sec = maxru(buf[BIND_OFF_MAXRU_SEC]);
2300     }
2301     if (buflen > BIND_OFF_MAXRU_PRI) {
2302 	maxru_pri = maxru(buf[BIND_OFF_MAXRU_PRI]);
2303     }
2304 
2305     /* Extract the screen size. */
2306     if (buflen > BIND_OFF_SSIZE) {
2307 	int bind_ss = buf[BIND_OFF_SSIZE];
2308 
2309 	switch (bind_ss) {
2310 	case 0x00:
2311 	case 0x02:
2312 	    bind_rd = MODEL_2_ROWS;
2313 	    bind_cd = MODEL_2_COLS;
2314 	    bind_ra = MODEL_2_ROWS;
2315 	    bind_ca = MODEL_2_COLS;
2316 	    bind_state = BIND_DIMS_PRESENT | BIND_DIMS_ALT | BIND_DIMS_VALID;
2317 	    break;
2318 	case 0x03:
2319 	    bind_rd = MODEL_2_ROWS;
2320 	    bind_cd = MODEL_2_COLS;
2321 	    bind_ra = maxROWS;
2322 	    bind_ca = maxCOLS;
2323 	    bind_state = BIND_DIMS_PRESENT | BIND_DIMS_VALID;
2324 	    break;
2325 	case 0x7e:
2326 	    bind_rd = buf[BIND_OFF_RD];
2327 	    bind_cd = buf[BIND_OFF_CD];
2328 	    bind_ra = buf[BIND_OFF_RD];
2329 	    bind_ca = buf[BIND_OFF_CD];
2330 	    bind_state = BIND_DIMS_PRESENT | BIND_DIMS_ALT | BIND_DIMS_VALID;
2331 	    break;
2332 	case 0x7f:
2333 	    bind_rd = buf[BIND_OFF_RD];
2334 	    bind_cd = buf[BIND_OFF_CD];
2335 	    bind_ra = buf[BIND_OFF_RA];
2336 	    bind_ca = buf[BIND_OFF_CA];
2337 	    bind_state = BIND_DIMS_PRESENT | BIND_DIMS_ALT | BIND_DIMS_VALID;
2338 	    break;
2339 	default:
2340 	    bind_state = 0;
2341 	    break;
2342 	}
2343     }
2344 
2345     /* Validate and implement the screen size. */
2346     if (appres.bind_limit && (bind_state & BIND_DIMS_PRESENT)) {
2347 	if (bind_rd > maxROWS || bind_cd > maxCOLS) {
2348 	    popup_an_error("Ignoring invalid BIND image screen "
2349 		    "size parameters:\n"
2350 		    " BIND Default Rows-Cols %ux%u > Maximum %ux%u",
2351 		    bind_rd, bind_cd, maxROWS, maxCOLS);
2352 	    bind_state &= ~BIND_DIMS_VALID;
2353 	} else if (bind_rd < MODEL_2_ROWS || bind_cd < MODEL_2_COLS) {
2354 	    popup_an_error("Ignoring invalid BIND image screen "
2355 		    "size parameters:\n"
2356 		    " BIND Default Rows-Cols %ux%u < Minimum %ux%u",
2357 		    bind_rd, bind_cd, MODEL_2_ROWS, MODEL_2_COLS);
2358 	    bind_state &= ~BIND_DIMS_VALID;
2359 	} else if (bind_ra > maxROWS || bind_ca > maxCOLS) {
2360 	    popup_an_error("Ignoring invalid BIND image screen "
2361 		    "size parameters:\n"
2362 		    " BIND Alternate Rows-Cols %ux%u > Maximum %ux%u",
2363 		    bind_ra, bind_ca, maxROWS, maxCOLS);
2364 	    bind_state &= ~BIND_DIMS_VALID;
2365 	} else if (bind_ra < MODEL_2_ROWS || bind_ca < MODEL_2_COLS) {
2366 	    popup_an_error("Ignoring invalid BIND image screen "
2367 		    "size parameters:\n"
2368 		    " BIND Alternate Rows-Cols %ux%u < Minimum %ux%u",
2369 		    bind_ra, bind_ca, MODEL_2_ROWS, MODEL_2_COLS);
2370 	    bind_state &= ~BIND_DIMS_VALID;
2371 	} else {
2372 	    defROWS = bind_rd;
2373 	    defCOLS = bind_cd;
2374 	    altROWS = bind_ra;
2375 	    altCOLS = bind_ca;
2376 	}
2377     }
2378 
2379     ctlr_erase(false);
2380 
2381     /* Extract the PLU name. */
2382     if (buflen > BIND_OFF_PLU_NAME_LEN) {
2383 	namelen = buf[BIND_OFF_PLU_NAME_LEN];
2384 	if (namelen > BIND_PLU_NAME_MAX) {
2385 	    namelen = BIND_PLU_NAME_MAX;
2386 	}
2387 	if ((namelen > 0) && (buflen > BIND_OFF_PLU_NAME + namelen)) {
2388 #if defined(EBCDIC_HOST) /*[*/
2389 	    memcpy(plu_name, &buf[BIND_OFF_PLU_NAME], namelen);
2390 	    plu_name[namelen] = '\0';
2391 #else /*][*/
2392 	    size_t i;
2393 
2394 	    for (i = 0; i < namelen; i++) {
2395 		size_t nx;
2396 
2397 		nx = ebcdic_to_multibyte(buf[BIND_OFF_PLU_NAME + i],
2398 			plu_name + dest_ix, mb_max_len(1));
2399 		if (nx > 1) {
2400 		    dest_ix += nx - 1;
2401 		}
2402 	    }
2403 #endif /*]*/
2404 	    status_lu(plu_name);
2405 	}
2406     }
2407 
2408     /* A BIND implicitly puts us in 3270 mode. */
2409     tn3270e_submode = E_3270;
2410 }
2411 
2412 /* Decode an UNBIND reason. */
2413 static const char *
unbind_reason(unsigned char r)2414 unbind_reason (unsigned char r)
2415 {
2416     switch (r) {
2417     case TN3270E_UNBIND_NORMAL:
2418 	return "normal";
2419     case TN3270E_UNBIND_BIND_FORTHCOMING:
2420 	return "BIND forthcoming";
2421     case TN3270E_UNBIND_VR_INOPERATIVE:
2422 	return "virtual route inoperative";
2423     case TN3270E_UNBIND_RX_INOPERATIVE:
2424 	return "route extension inoperative";
2425     case TN3270E_UNBIND_HRESET:
2426 	return "hierarchical reset";
2427     case TN3270E_UNBIND_SSCP_GONE:
2428 	return "SSCP gone";
2429     case TN3270E_UNBIND_VR_DEACTIVATED:
2430 	return "virtual route deactivated";
2431     case TN3270E_UNBIND_LU_FAILURE_PERM:
2432 	return "unrecoverable LU failure";
2433     case TN3270E_UNBIND_LU_FAILURE_TEMP:
2434 	return "recoverable LU failure";
2435     case TN3270E_UNBIND_CLEANUP:
2436 	return "cleanup";
2437     case TN3270E_UNBIND_BAD_SENSE:
2438 	return "bad sense code or user-supplied sense code";
2439     default:
2440 	return lazyaf("unknown X'%02x'", r);
2441     }
2442 }
2443 
2444 static int
process_eor(void)2445 process_eor(void)
2446 {
2447     if (syncing || !(ibptr - ibuf)) {
2448 	return(0);
2449     }
2450 
2451     if (IN_E) {
2452 	tn3270e_header *h = (tn3270e_header *)ibuf;
2453 	unsigned char *s;
2454 	enum pds rv;
2455 
2456 	vtrace("RCVD TN3270E(%s%s %s %u)\n",
2457 		e_dt(h->data_type),
2458 		e_rq(h->data_type, h->request_flag),
2459 		e_rsp(h->data_type, h->response_flag),
2460 		h->seq_number[0] << 8 | h->seq_number[1]);
2461 
2462 	switch (h->data_type) {
2463 	case TN3270E_DT_3270_DATA:
2464 	    if (b8_bit_is_set(&e_funcs, TN3270E_FUNC_BIND_IMAGE) &&
2465 		    !tn3270e_bound) {
2466 		return 0;
2467 	    }
2468 	    tn3270e_submode = E_3270;
2469 	    check_in3270();
2470 	    response_required = h->response_flag;
2471 	    rv = process_ds(ibuf + EH_SIZE, (ibptr - ibuf) - EH_SIZE);
2472 	    if (rv < 0 && response_required != TN3270E_RSF_NO_RESPONSE) {
2473 		tn3270e_nak(rv);
2474 	    }
2475 	    else if (rv == PDS_OKAY_NO_OUTPUT &&
2476 		    response_required == TN3270E_RSF_ALWAYS_RESPONSE) {
2477 		tn3270e_ack();
2478 	    }
2479 	    response_required = TN3270E_RSF_NO_RESPONSE;
2480 	    return 0;
2481 	case TN3270E_DT_BIND_IMAGE:
2482 	    if (!b8_bit_is_set(&e_funcs, TN3270E_FUNC_BIND_IMAGE)) {
2483 		return 0;
2484 	    }
2485 	    process_bind(ibuf + EH_SIZE, (ibptr - ibuf) - EH_SIZE);
2486 	    if (bind_state & BIND_DIMS_PRESENT) {
2487 		if (bind_state & BIND_DIMS_ALT) {
2488 		    trace_ds("< BIND PLU-name '%s' "
2489 			    "MaxSec-RU %d MaxPri-RU %d "
2490 			    "Rows-Cols Default %dx%d "
2491 			    "Alternate %dx%d%s%s\n",
2492 			    plu_name, maxru_sec, maxru_pri,
2493 			    bind_rd, bind_cd,
2494 			    bind_ra, bind_ca,
2495 			    (bind_state & BIND_DIMS_VALID)?
2496 				"": " (invalid)",
2497 			    appres.bind_limit?
2498 				"": " (ignored)");
2499 		} else {
2500 		    trace_ds("< BIND PLU-name '%s' "
2501 			    "MaxSec-RU %d MaxPri-RU %d "
2502 			    "Rows-Cols Default %dx%d%s%s\n",
2503 			    plu_name, maxru_sec, maxru_pri,
2504 			    bind_rd, bind_cd,
2505 			    (bind_state & BIND_DIMS_VALID)?
2506 				"": " (invalid)",
2507 			    appres.bind_limit?
2508 				"": " (ignored)");
2509 		}
2510 	    } else {
2511 		trace_ds("< BIND PLU-name '%s' "
2512 			"MaxSec-RU %d MaxPri-RU %d\n",
2513 			plu_name, maxru_sec, maxru_pri);
2514 	    }
2515 	    tn3270e_bound = 1;
2516 	    check_in3270();
2517 	    return 0;
2518 	case TN3270E_DT_UNBIND:
2519 	    if (!b8_bit_is_set(&e_funcs, TN3270E_FUNC_BIND_IMAGE)) {
2520 		return 0;
2521 	    }
2522 	    if ((ibptr - ibuf) > EH_SIZE) {
2523 		trace_ds("< UNBIND %s\n", unbind_reason(ibuf[EH_SIZE]));
2524 	    }
2525 	    tn3270e_bound = 0;
2526 	    /* Go back to the connected LU. */
2527 	    status_lu(connected_lu);
2528 	    /*
2529 	     * Undo any screen-sizing effects from a previous BIND.
2530 	     */
2531 	    defROWS = MODEL_2_ROWS;
2532 	    defCOLS = MODEL_2_COLS;
2533 	    altROWS = maxROWS;
2534 	    altCOLS = maxCOLS;
2535 	    ctlr_erase(false);
2536 	    tn3270e_submode = E_UNBOUND;
2537 	    check_in3270();
2538 	    return 0;
2539 	case TN3270E_DT_NVT_DATA:
2540 	    /* In tn3270e NVT mode */
2541 	    tn3270e_submode = E_NVT;
2542 	    check_in3270();
2543 	    for (s = ibuf; s < ibptr; s++) {
2544 		nvt_process(*s++);
2545 	    }
2546 	    return 0;
2547 	case TN3270E_DT_SSCP_LU_DATA:
2548 	    if (!b8_bit_is_set(&e_funcs, TN3270E_FUNC_BIND_IMAGE)) {
2549 		return 0;
2550 	    }
2551 	    tn3270e_submode = E_SSCP;
2552 	    check_in3270();
2553 	    ctlr_write_sscp_lu(ibuf + EH_SIZE, (ibptr - ibuf) - EH_SIZE);
2554 	    return 0;
2555 	default:
2556 	    /* Should do something more extraordinary here. */
2557 	    return 0;
2558 	}
2559     } else {
2560 	process_ds(ibuf, ibptr - ibuf);
2561     }
2562     return 0;
2563 }
2564 
2565 /*
2566  * net_exception
2567  *	Called when there is an exceptional condition on the socket.
2568  */
2569 void
net_exception(iosrc_t fd _is_unused,ioid_t id _is_unused)2570 net_exception(iosrc_t fd _is_unused, ioid_t id _is_unused)
2571 {
2572 #if defined(LOCAL_PROCESS) /*[*/
2573     if (local_process) {
2574 	vtrace("RCVD exception\n");
2575     } else
2576 #endif /*[*/
2577     {
2578 	vtrace("RCVD urgent data indication\n");
2579 	if (!syncing) {
2580 	    syncing = 1;
2581 	    x_except_off();
2582 	}
2583     }
2584 }
2585 
2586 /*
2587  * Flavors of Network Output:
2588  *
2589  *   3270 mode
2590  *	net_output	send a 3270 record
2591  *
2592  *   NVT mode; call each other in turn
2593  *	net_sendc	net_cookout for 1 byte
2594  *	net_sends	net_cookout for a null-terminated string
2595  *	net_cookout	send user data with cooked-mode processing, NVT mode
2596  *	net_cookedout	send user data, NVT mode, already cooked
2597  *	net_rawout	send telnet protocol data, NVT mode
2598  *
2599  */
2600 
2601 /*
2602  * net_cookedout
2603  *      Send user data out in NVT mode, without cooked-mode processing.
2604  */
2605 void
net_cookedout(const char * buf,size_t len)2606 net_cookedout(const char *buf, size_t len)
2607 {
2608     if (toggled(TRACING)) {
2609 	size_t i;
2610 
2611 	vtrace(">");
2612 	for (i = 0; i < len; i++) {
2613 	    vtrace(" %s", ctl_see((int)*(buf+i)));
2614 	}
2615 	vtrace("\n");
2616     }
2617     net_rawout((unsigned const char *)buf, len);
2618 }
2619 
2620 /*
2621  * net_cookout
2622  *      Send output in NVT mode, including cooked-mode processing if
2623  *      appropriate.
2624  */
2625 void
net_cookout(const char * buf,size_t len)2626 net_cookout(const char *buf, size_t len)
2627 {
2628     if (!IN_NVT || (kybdlock & KL_AWAITING_FIRST)) {
2629 	return;
2630     }
2631 
2632     if (linemode) {
2633 	linemode_out(buf, len);
2634     } else {
2635 	net_cookedout(buf, len);
2636     }
2637 }
2638 
2639 /*
2640  * net_rawout
2641  *	Send out raw telnet data.  We assume that there will always be enough
2642  *	space to buffer what we want to transmit, so we don't handle EAGAIN or
2643  *	EWOULDBLOCK.
2644  */
2645 static void
net_rawout(unsigned const char * buf,size_t len)2646 net_rawout(unsigned const char *buf, size_t len)
2647 {
2648     int nw;
2649 
2650     trace_netdata('>', buf, len);
2651 
2652     while (len) {
2653 #if defined(OMTU) /*[*/
2654 	size_t n2w = len;
2655 	int pause = 0;
2656 
2657 	if (n2w > OMTU) {
2658 	    n2w = OMTU;
2659 	    pause = 1;
2660 	}
2661 #else
2662 # define n2w len
2663 #endif
2664 	if (secure_connection) {
2665 	    nw = sio_write(sio, (const char *) buf, (int)n2w);
2666 	} else
2667 #if defined(LOCAL_PROCESS) /*[*/
2668 	if (local_process) {
2669 	    nw = write(sock, (const char *) buf, (int)n2w);
2670 	} else
2671 #endif /*]*/
2672 	{
2673 	    nw = send(sock, (const char *) buf, (int)n2w, 0);
2674 	}
2675 	if (nw < 0) {
2676 	    if (secure_connection) {
2677 		connect_error("%s", sio_last_error());
2678 		host_disconnect(false);
2679 		return;
2680 	    }
2681 	    vtrace("RCVD socket error %d (%s)\n", socket_errno(),
2682 		    socket_strerror(socket_errno()));
2683 	    if (socket_errno() == SE_EPIPE || socket_errno() == SE_ECONNRESET) {
2684 		host_disconnect(false);
2685 		return;
2686 	    } else if (socket_errno() == SE_EINTR) {
2687 		goto bot;
2688 	    } else {
2689 		popup_a_sockerr("Socket write");
2690 		host_disconnect(true);
2691 		return;
2692 	    }
2693 	}
2694 	ns_bsent += nw;
2695 	stats_poke();
2696 	len -= nw;
2697 	buf += nw;
2698     bot:
2699 #if defined(OMTU) /*[*/
2700 	if (pause) {
2701 	    sleep(1);
2702 	}
2703 #endif /*]*/
2704     	;
2705     }
2706 }
2707 
2708 /*
2709  * net_hexnvt_out_framed
2710  *	Send uncontrolled user data to the host in NVT mode, performing IAC
2711  *	and CR quoting as necessary.
2712  */
2713 static void
net_hexnvt_out_framed(unsigned char * buf,int len,bool framed)2714 net_hexnvt_out_framed(unsigned char *buf, int len, bool framed)
2715 {
2716     unsigned char *tbuf;
2717     unsigned char *xbuf;
2718     bool first = true;
2719 
2720     if (!len) {
2721 	return;
2722     }
2723 
2724     if (HOST_FLAG(NO_TELNET_HOST)) {
2725 	net_rawout(buf, len);
2726 	return;
2727     }
2728 
2729     /* Expand it. */
2730     tbuf = xbuf = (unsigned char *)Malloc(2*len);
2731     while (len) {
2732 	unsigned char c = *buf++;
2733 
2734 	*tbuf++ = c;
2735 	len--;
2736 	if (framed && (first || len == 1)) {
2737 	    /* Don't quote initial IAC or trailing IAC SE. */
2738 	    first = false;
2739 	    continue;
2740 	}
2741 	if (c == IAC) {
2742 	    *tbuf++ = IAC;
2743 	} else if (c == '\r' && (!len || *buf != '\n')) {
2744 	    *tbuf++ = '\0';
2745 	}
2746 	first = false;
2747     }
2748 
2749     /* Send it to the host. */
2750     net_rawout(xbuf, tbuf - xbuf);
2751     Free(xbuf);
2752 }
2753 
2754 /*
2755  * net_hexnvt_out
2756  *	Send uncontrolled user data to the host in NVT mode, performing IAC
2757  *	and CR quoting as necessary.
2758  */
2759 void
net_hexnvt_out(unsigned char * buf,int len)2760 net_hexnvt_out(unsigned char *buf, int len)
2761 {
2762     net_hexnvt_out_framed(buf, len, false);
2763 }
2764 
2765 /*
2766  * check_in3270
2767  *	Check for switches between NVT, SSCP-LU and 3270 modes.
2768  */
2769 static void
check_in3270(void)2770 check_in3270(void)
2771 {
2772     enum cstate new_cstate = NOT_CONNECTED;
2773 
2774     if (myopts[TELOPT_TN3270E]) {
2775 	if (!tn3270e_negotiated) {
2776 	    new_cstate = CONNECTED_UNBOUND;
2777 	} else switch (tn3270e_submode) {
2778 	    case E_UNBOUND:
2779 		new_cstate = CONNECTED_UNBOUND;
2780 		break;
2781 	    case E_NVT:
2782 		new_cstate = CONNECTED_E_NVT;
2783 		break;
2784 	    case E_3270:
2785 		new_cstate = CONNECTED_TN3270E;
2786 		break;
2787 	    case E_SSCP:
2788 		new_cstate = CONNECTED_SSCP;
2789 		break;
2790 	    }
2791     } else if (myopts[TELOPT_BINARY] &&
2792 	       myopts[TELOPT_EOR] &&
2793 	       myopts[TELOPT_TTYPE] &&
2794 	       hisopts[TELOPT_BINARY] &&
2795 	       hisopts[TELOPT_EOR]) {
2796 	new_cstate = CONNECTED_3270;
2797     } else if (cstate == TELNET_PENDING) {
2798 	/* Nothing has happened, yet. */
2799 	return;
2800     } else if (appres.nvt_mode || HOST_FLAG(ANSI_HOST)) {
2801 	new_cstate = linemode? CONNECTED_NVT: CONNECTED_NVT_CHAR;
2802     } else {
2803 	new_cstate = TELNET_PENDING;
2804     }
2805 
2806     if (new_cstate != cstate) {
2807 	int was_in_e = IN_E;
2808 
2809 	/*
2810 	 * If we've now switched between non-TN3270E mode and
2811 	 * TN3270E mode, reset the LU list so we can try again
2812 	 * in the new mode.
2813 	 */
2814 	if (lus != NULL && was_in_e != IN_E) {
2815 	    curr_lu = lus;
2816 	    try_lu = *curr_lu;
2817 	}
2818 
2819 	/* Allocate the initial 3270 input buffer. */
2820 	if (new_cstate >= TELNET_PENDING && !ibuf_size) {
2821 	    ibuf = (unsigned char *)Malloc(BUFSIZ);
2822 	    ibuf_size = BUFSIZ;
2823 	    ibptr = ibuf;
2824 	}
2825 
2826 	/* Reinitialize line mode. */
2827 	if ((new_cstate == CONNECTED_NVT && linemode) ||
2828 		new_cstate == CONNECTED_E_NVT) {
2829 	    linemode_buf_init();
2830 	}
2831 
2832 	/* If we fell out of TN3270E, remove the state. */
2833 	if (!myopts[TELOPT_TN3270E]) {
2834 	    tn3270e_negotiated = 0;
2835 	    tn3270e_submode = E_UNBOUND;
2836 	    tn3270e_bound = 0;
2837 	}
2838 	vtrace("Now operating in %s mode.\n", state_name[new_cstate]);
2839 	if (FULL_SESSION) {
2840 	    any_host_data = true;
2841 	}
2842 	host_in3270(new_cstate);
2843     }
2844 }
2845 
2846 /*
2847  * store3270in
2848  *	Store a character in the 3270 input buffer, checking for buffer
2849  *	overflow and reallocating ibuf if necessary.
2850  */
2851 static void
store3270in(unsigned char c)2852 store3270in(unsigned char c)
2853 {
2854     if (ibptr - ibuf >= ibuf_size) {
2855 	ibuf_size += BUFSIZ;
2856 	ibuf = (unsigned char *)Realloc((char *)ibuf, ibuf_size);
2857 	ibptr = ibuf + ibuf_size - BUFSIZ;
2858     }
2859     *ibptr++ = c;
2860 }
2861 
2862 /*
2863  * space3270out
2864  *	Ensure that <n> more characters will fit in the 3270 output buffer.
2865  *	Allocates the buffer in BUFSIZ chunks.
2866  *	Allocates hidden space at the front of the buffer for TN3270E.
2867  */
2868 void
space3270out(size_t n)2869 space3270out(size_t n)
2870 {
2871     size_t nc = 0;	/* amount of data currently in obuf */
2872     unsigned more = 0;
2873 
2874     if (obuf_size) {
2875 	nc = obptr - obuf;
2876     }
2877 
2878     while ((nc + n + EH_SIZE) > (obuf_size + more)) {
2879 	more += BUFSIZ;
2880     }
2881 
2882     if (more) {
2883 	obuf_size += more;
2884 	obuf_base = (unsigned char *)Realloc((char *)obuf_base, obuf_size);
2885 	obuf = obuf_base + EH_SIZE;
2886 	obptr = obuf + nc;
2887     }
2888 }
2889 
2890 /*
2891  * check_linemode
2892  *	Set the global variable 'linemode', which says whether we are in
2893  *	character-by-character mode or line mode.
2894  */
2895 static void
check_linemode(bool init)2896 check_linemode(bool init)
2897 {
2898     bool wasline = linemode;
2899 
2900     /*
2901      * The next line is a deliberate kluge to effectively ignore the SGA
2902      * option.  If the host will echo for us, we assume
2903      * character-at-a-time; otherwise we assume fully cooked by us.
2904      *
2905      * This allows certain IBM hosts which volunteer SGA but refuse
2906      * ECHO to operate more-or-less normally, at the expense of
2907      * implementing the (hopefully useless) "character-at-a-time, local
2908      * echo" mode.
2909      *
2910      * We still implement "switch to line mode" and "switch to character
2911      * mode" properly by asking for both SGA and ECHO to be off or on, but
2912      * we basically ignore the reply for SGA.
2913      */
2914     linemode = !hisopts[TELOPT_ECHO] /* && !hisopts[TELOPT_SGA] */;
2915 
2916     if (init || linemode != wasline) {
2917 	if (cstate == CONNECTED_NVT || cstate == CONNECTED_NVT_CHAR) {
2918 	    host_in3270(linemode? CONNECTED_NVT: CONNECTED_NVT_CHAR);
2919 	}
2920 	st_changed(ST_LINE_MODE, linemode);
2921 	if (!init) {
2922 	    vtrace("Operating in %s mode.\n",
2923 		    linemode? "line": "character-at-a-time");
2924 	}
2925 	if (IN_NVT) {
2926 	    if (linemode) {
2927 		linemode_buf_init();
2928 	    } else {
2929 		linemode_dump();
2930 	    }
2931 	}
2932     }
2933 }
2934 
2935 /*
2936  * nnn
2937  *	Expands a number to a character string, for displaying unknown telnet
2938  *	commands and options.
2939  */
2940 static const char *
nnn(int c)2941 nnn(int c)
2942 {
2943     return lazyaf("%d", c);
2944 }
2945 
2946 /*
2947  * cmd
2948  *	Expands a TELNET command into a character string.
2949  */
2950 const char *
cmd(int c)2951 cmd(int c)
2952 {
2953     if (TELCMD_OK(c)) {
2954 	return TELCMD(c);
2955     } else {
2956 	return nnn(c);
2957     }
2958 }
2959 
2960 /*
2961  * opt
2962  *	Expands a TELNET option into a character string.
2963  */
2964 const char *
opt(unsigned char c)2965 opt(unsigned char c)
2966 {
2967     if (TELOPT_OK(c)) {
2968 	return TELOPT(c);
2969     } else if (c == TELOPT_TN3270E) {
2970 	return "TN3270E";
2971     } else if (c == TELOPT_STARTTLS) {
2972 	return "START-TLS";
2973     } else {
2974 	return nnn((int)c);
2975     }
2976 }
2977 
2978 
2979 #define LINEDUMP_MAX	32
2980 
2981 void
trace_netdata(char direction,unsigned const char * buf,size_t len)2982 trace_netdata(char direction, unsigned const char *buf, size_t len)
2983 {
2984     size_t offset;
2985 
2986     if (!toggled(TRACING)) {
2987 	    return;
2988     }
2989     for (offset = 0; offset < len; offset++) {
2990 	if (!(offset % LINEDUMP_MAX)) {
2991 	    ntvtrace("%s%c 0x%-3x ", (offset? "\n": ""), direction,
2992 		    (unsigned)offset);
2993 	}
2994 	ntvtrace("%02x", buf[offset]);
2995     }
2996     ntvtrace("\n");
2997 }
2998 
2999 /*
3000  * net_output
3001  *	Send 3270 output over the network:
3002  *	- Prepend TN3270E header
3003  *	- Expand IAC to IAC IAC
3004  *	- Append IAC EOR
3005  */
3006 void
net_output(void)3007 net_output(void)
3008 {
3009     static unsigned char *xobuf = NULL;
3010     static int xobuf_len = 0;
3011     int need_resize = 0;
3012     unsigned char *nxoptr, *xoptr;
3013 
3014 #define BSTART	((IN_TN3270E || IN_SSCP)? obuf_base: obuf)
3015 
3016     /* Set the TN3720E header. */
3017     if (IN_TN3270E || IN_SSCP) {
3018 	tn3270e_header *h = (tn3270e_header *)obuf_base;
3019 
3020 	/* Check for sending a TN3270E response. */
3021 	if (response_required == TN3270E_RSF_ALWAYS_RESPONSE) {
3022 	    tn3270e_ack();
3023 	    response_required = TN3270E_RSF_NO_RESPONSE;
3024 	}
3025 
3026 	/* Set the outbound TN3270E header. */
3027 	h->data_type = IN_TN3270E? TN3270E_DT_3270_DATA:
3028 	    TN3270E_DT_SSCP_LU_DATA;
3029 	h->request_flag = 0;
3030 	h->response_flag = 0;
3031 	h->seq_number[0] = (e_xmit_seq >> 8) & 0xff;
3032 	h->seq_number[1] = e_xmit_seq & 0xff;
3033 
3034 	vtrace("SENT TN3270E(%s NO-RESPONSE %u)\n",
3035 		IN_TN3270E? "3270-DATA": "SSCP-LU-DATA", e_xmit_seq);
3036 	if (b8_bit_is_set(&e_funcs, TN3270E_FUNC_RESPONSES)) {
3037 		e_xmit_seq = (e_xmit_seq + 1) & 0x7fff;
3038 	}
3039     }
3040 
3041     /* Reallocate the expanded output buffer. */
3042     while (xobuf_len <  (obptr - BSTART + 1) * 2) {
3043 	xobuf_len += BUFSZ;
3044 	need_resize++;
3045     }
3046     if (need_resize) {
3047 	Replace(xobuf, (unsigned char *)Malloc(xobuf_len));
3048     }
3049 
3050     /* Copy and expand IACs. */
3051     xoptr = xobuf;
3052     nxoptr = BSTART;
3053     while (nxoptr < obptr) {
3054 	if ((*xoptr++ = *nxoptr++) == IAC) {
3055 	    *xoptr++ = IAC;
3056 	}
3057     }
3058 
3059     /* Append the IAC EOR and transmit. */
3060     *xoptr++ = IAC;
3061     *xoptr++ = EOR;
3062     net_rawout(xobuf, xoptr - xobuf);
3063 
3064     vtrace("SENT EOR\n");
3065     ns_rsent++;
3066     stats_poke();
3067 #undef BSTART
3068 }
3069 
3070 /* Send a TN3270E positive response to the server. */
3071 static void
tn3270e_ack(void)3072 tn3270e_ack(void)
3073 {
3074     unsigned char rsp_buf[10];
3075     tn3270e_header *h_in = (tn3270e_header *)ibuf;
3076     int rsp_len = 0;
3077 
3078     rsp_len = 0;
3079     rsp_buf[rsp_len++] = TN3270E_DT_RESPONSE;	    /* data_type */
3080     rsp_buf[rsp_len++] = 0;			    /* request_flag */
3081     rsp_buf[rsp_len++] = TN3270E_RSF_POSITIVE_RESPONSE; /* response_flag */
3082     rsp_buf[rsp_len++] = h_in->seq_number[0];	    /* seq_number[0] */
3083     if (h_in->seq_number[0] == IAC) {
3084 	rsp_buf[rsp_len++] = IAC;
3085     }
3086     rsp_buf[rsp_len++] = h_in->seq_number[1];	    /* seq_number[1] */
3087     if (h_in->seq_number[1] == IAC) {
3088 	rsp_buf[rsp_len++] = IAC;
3089     }
3090     rsp_buf[rsp_len++] = TN3270E_POS_DEVICE_END;
3091     rsp_buf[rsp_len++] = IAC;
3092     rsp_buf[rsp_len++] = EOR;
3093     vtrace("SENT TN3270E(RESPONSE POSITIVE-RESPONSE %u) DEVICE-END\n",
3094 	    h_in->seq_number[0] << 8 | h_in->seq_number[1]);
3095     net_rawout(rsp_buf, rsp_len);
3096 }
3097 
3098 /* Send a TN3270E negative response to the server. */
3099 static void
tn3270e_nak(enum pds rv)3100 tn3270e_nak(enum pds rv)
3101 {
3102     unsigned char rsp_buf[10];
3103     tn3270e_header *h_in = (tn3270e_header *)ibuf;
3104     int rsp_len = 0;
3105     char *neg = NULL;
3106 
3107     rsp_buf[rsp_len++] = TN3270E_DT_RESPONSE;	    /* data_type */
3108     rsp_buf[rsp_len++] = 0;			    /* request_flag */
3109     rsp_buf[rsp_len++] = TN3270E_RSF_NEGATIVE_RESPONSE; /* response_flag */
3110     rsp_buf[rsp_len++] = h_in->seq_number[0];	    /* seq_number[0] */
3111     if (h_in->seq_number[0] == IAC) {
3112 	rsp_buf[rsp_len++] = IAC;
3113     }
3114     rsp_buf[rsp_len++] = h_in->seq_number[1];	    /* seq_number[1] */
3115     if (h_in->seq_number[1] == IAC) {
3116 	rsp_buf[rsp_len++] = IAC;
3117     }
3118     switch (rv) {
3119     default:
3120     case PDS_BAD_CMD:
3121 	rsp_buf[rsp_len++] = TN3270E_NEG_COMMAND_REJECT;
3122 	neg = "COMMAND-REJECT";
3123 	break;
3124     case PDS_BAD_ADDR:
3125 	rsp_buf[rsp_len++] = TN3270E_NEG_OPERATION_CHECK;
3126 	neg = "OPERATION-CHECK";
3127 	break;
3128     }
3129     rsp_buf[rsp_len++] = IAC;
3130     rsp_buf[rsp_len++] = EOR;
3131     vtrace("SENT TN3270E(RESPONSE NEGATIVE-RESPONSE %u) %s\n",
3132 	    h_in->seq_number[0] << 8 | h_in->seq_number[1], neg);
3133     net_rawout(rsp_buf, rsp_len);
3134 }
3135 
3136 /* Add a dummy TN3270E header to the output buffer. */
3137 bool
net_add_dummy_tn3270e(void)3138 net_add_dummy_tn3270e(void)
3139 {
3140     tn3270e_header *h;
3141 
3142     if (!IN_E || tn3270e_submode == E_UNBOUND) {
3143 	return false;
3144     }
3145 
3146     space3270out(EH_SIZE);
3147     h = (tn3270e_header *)obptr;
3148 
3149     switch (tn3270e_submode) {
3150     case E_UNBOUND:
3151 	break;
3152     case E_NVT:
3153 	h->data_type = TN3270E_DT_NVT_DATA;
3154 	break;
3155     case E_SSCP:
3156 	h->data_type = TN3270E_DT_SSCP_LU_DATA;
3157 	break;
3158     case E_3270:
3159 	h->data_type = TN3270E_DT_3270_DATA;
3160 	break;
3161     }
3162     h->request_flag = 0;
3163     h->response_flag = TN3270E_RSF_NO_RESPONSE;
3164     h->seq_number[0] = 0;
3165     h->seq_number[1] = 0;
3166     obptr += EH_SIZE;
3167     return true;
3168 }
3169 
3170 /*
3171  * Add IAC EOR to a buffer.
3172  */
3173 void
net_add_eor(unsigned char * buf,size_t len)3174 net_add_eor(unsigned char *buf, size_t len)
3175 {
3176     buf[len++] = IAC;
3177     buf[len++] = EOR;
3178 }
3179 
3180 /*
3181  * net_sendc
3182  *	Send a character of user data over the network in NVT mode.
3183  */
3184 void
net_sendc(char c)3185 net_sendc(char c)
3186 {
3187     if (c == '\r' && !linemode
3188 #if defined(LOCAL_PROCESS) /*[*/
3189 			       && !local_process
3190 #endif /*]*/
3191 						) {
3192 		/* CR must be quoted */
3193 	net_cookout("\r\0", 2);
3194     } else {
3195 	net_cookout(&c, 1);
3196     }
3197 }
3198 
3199 /*
3200  * net_sends
3201  *	Send a null-terminated string of user data in NVT mode.
3202  */
3203 void
net_sends(const char * s)3204 net_sends(const char *s)
3205 {
3206     net_cookout(s, strlen(s));
3207 }
3208 
3209 /*
3210  * External entry points to negotiate line or character mode.
3211  */
3212 void
net_linemode(void)3213 net_linemode(void)
3214 {
3215     if (!CONNECTED) {
3216 	return;
3217     }
3218     if (!HOST_FLAG(NO_TELNET_HOST)) {
3219 	if (hisopts[TELOPT_ECHO]) {
3220 	    dont_opt[2] = TELOPT_ECHO;
3221 	    net_rawout(dont_opt, sizeof(dont_opt));
3222 	    vtrace("SENT %s %s\n", cmd(DONT), opt(TELOPT_ECHO));
3223 	}
3224 	if (hisopts[TELOPT_SGA]) {
3225 	    dont_opt[2] = TELOPT_SGA;
3226 	    net_rawout(dont_opt, sizeof(dont_opt));
3227 	    vtrace("SENT %s %s\n", cmd(DONT), opt(TELOPT_SGA));
3228 	}
3229     } else {
3230 	hisopts[TELOPT_ECHO] = 0;
3231 	hisopts[TELOPT_SGA] = 0;
3232 	check_linemode(false);
3233     }
3234 }
3235 
3236 void
net_charmode(void)3237 net_charmode(void)
3238 {
3239     if (!CONNECTED) {
3240 	return;
3241     }
3242     if (!HOST_FLAG(NO_TELNET_HOST)) {
3243 	if (!hisopts[TELOPT_ECHO]) {
3244 	    do_opt[2] = TELOPT_ECHO;
3245 	    net_rawout(do_opt, sizeof(do_opt));
3246 	    vtrace("SENT %s %s\n", cmd(DO), opt(TELOPT_ECHO));
3247 	}
3248 	if (!hisopts[TELOPT_SGA]) {
3249 	    do_opt[2] = TELOPT_SGA;
3250 	    net_rawout(do_opt, sizeof(do_opt));
3251 	    vtrace("SENT %s %s\n", cmd(DO), opt(TELOPT_SGA));
3252 	}
3253     } else {
3254 	hisopts[TELOPT_ECHO] = 1;
3255 	hisopts[TELOPT_SGA] = 1;
3256 	check_linemode(false);
3257     }
3258 }
3259 
3260 /*
3261  * net_break
3262  *	Send telnet break, which is used to implement 3270 ATTN.
3263  *
3264  */
3265 void
net_break(char c)3266 net_break(char c)
3267 {
3268     if (!HOST_FLAG(NO_TELNET_HOST)) {
3269 	static unsigned char buf[] = { IAC, BREAK };
3270 
3271 	/* I don't know if we should first send TELNET synch ? */
3272 	net_rawout(buf, sizeof(buf));
3273 	vtrace("SENT BREAK\n");
3274     } else if (c != '\0') {
3275 	net_rawout((unsigned char *)&c, 1);
3276     }
3277 }
3278 
3279 /*
3280  * net_interrupt
3281  *	Send telnet IP.
3282  *
3283  */
3284 void
net_interrupt(char c)3285 net_interrupt(char c)
3286 {
3287     if (!HOST_FLAG(NO_TELNET_HOST)) {
3288 	static unsigned char buf[] = { IAC, IP };
3289 
3290 	/* I don't know if we should first send TELNET synch ? */
3291 	net_rawout(buf, sizeof(buf));
3292 	vtrace("SENT IP\n");
3293     } else if (c != '\0') {
3294 	net_rawout((unsigned char *)&c, 1);
3295     }
3296 }
3297 
3298 /*
3299  * net_abort
3300  *	Send telnet AO.
3301  *
3302  */
3303 void
net_abort(void)3304 net_abort(void)
3305 {
3306     static unsigned char buf[] = { IAC, AO };
3307 
3308     if (b8_bit_is_set(&e_funcs, TN3270E_FUNC_SYSREQ)) {
3309 	/*
3310 	 * I'm not sure yet what to do here.  Should the host respond
3311 	 * to the AO by sending us SSCP-LU data (and putting us into
3312 	 * SSCP-LU mode), or should we put ourselves in it?
3313 	 * Time, and testers, will tell.
3314 	 */
3315 	switch (tn3270e_submode) {
3316 	case E_UNBOUND:
3317 	case E_NVT:
3318 	    break;
3319 	case E_SSCP:
3320 	    net_rawout(buf, sizeof(buf));
3321 	    vtrace("SENT AO\n");
3322 	    if (tn3270e_bound || !b8_bit_is_set(&e_funcs,
3323 					TN3270E_FUNC_BIND_IMAGE)) {
3324 		    tn3270e_submode = E_3270;
3325 		    check_in3270();
3326 	    }
3327 	    break;
3328 	case E_3270:
3329 	    net_rawout(buf, sizeof(buf));
3330 	    vtrace("SENT AO\n");
3331 	    tn3270e_submode = E_SSCP;
3332 	    check_in3270();
3333 	    break;
3334 	}
3335     }
3336 }
3337 
3338 /*
3339  * Construct a string to reproduce the current TELNET options.
3340  * Returns a bool indicating whether it is necessary.
3341  */
3342 bool
net_snap_options(void)3343 net_snap_options(void)
3344 {
3345     bool any = false;
3346     int i;
3347     static unsigned char ttype_str[] = {
3348 	IAC, DO, TELOPT_TTYPE,
3349 	IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE
3350     };
3351 
3352     if (!CONNECTED) {
3353 	return false;
3354     }
3355 
3356     obptr = obuf;
3357 
3358     /* Do TTYPE first. */
3359     if (myopts[TELOPT_TTYPE]) {
3360 	unsigned j;
3361 
3362 	space3270out(sizeof(ttype_str));
3363 	for (j = 0; j < sizeof(ttype_str); j++) {
3364 	    *obptr++ = ttype_str[j];
3365 	}
3366     }
3367 
3368     /* Do the other options. */
3369     for (i = 0; i < N_OPTS; i++) {
3370 	space3270out(6);
3371 	if (i == TELOPT_TTYPE) {
3372 	    continue;
3373 	}
3374 	if (hisopts[i]) {
3375 	    *obptr++ = IAC;
3376 	    *obptr++ = WILL;
3377 	    *obptr++ = (unsigned char)i;
3378 	    any = true;
3379 	}
3380 	if (myopts[i]) {
3381 	    *obptr++ = IAC;
3382 	    *obptr++ = DO;
3383 	    *obptr++ = (unsigned char)i;
3384 	    any = true;
3385 	}
3386     }
3387 
3388     /* If we're in TN3270E mode, snap the subnegotations as well. */
3389     if (myopts[TELOPT_TN3270E]) {
3390 	any = true;
3391 
3392 	space3270out(5 +
3393 		((connected_type != NULL)? strlen(connected_type): 0) +
3394 		((connected_lu != NULL)? + strlen(connected_lu): 0) +
3395 		2);
3396 	*obptr++ = IAC;
3397 	*obptr++ = SB;
3398 	*obptr++ = TELOPT_TN3270E;
3399 	*obptr++ = TN3270E_OP_DEVICE_TYPE;
3400 	*obptr++ = TN3270E_OP_IS;
3401 	if (connected_type != NULL) {
3402 	    memcpy(obptr, connected_type, strlen(connected_type));
3403 	    obptr += strlen(connected_type);
3404 	}
3405 	if (connected_lu != NULL) {
3406 	    *obptr++ = TN3270E_OP_CONNECT;
3407 	    memcpy(obptr, connected_lu, strlen(connected_lu));
3408 	    obptr += strlen(connected_lu);
3409 	}
3410 	*obptr++ = IAC;
3411 	*obptr++ = SE;
3412 
3413 	space3270out(38);
3414 	memcpy(obptr, functions_req, 4);
3415 	obptr += 4;
3416 	*obptr++ = TN3270E_OP_IS;
3417 	for (i = 0; i < MX8; i++) {
3418 	    if (b8_bit_is_set(&e_funcs, i)) {
3419 		*obptr++ = i;
3420 	    }
3421 	}
3422 	*obptr++ = IAC;
3423 	*obptr++ = SE;
3424 
3425 	if (tn3270e_bound) {
3426 	    tn3270e_header *h;
3427 	    size_t i;
3428 	    int xlen = 0;
3429 
3430 	    for (i = 0; i < bind_image_len; i++)  {
3431 		if (bind_image[i] == 0xff)
3432 		    xlen++;
3433 	    }
3434 
3435 	    space3270out(EH_SIZE + bind_image_len + xlen + 3);
3436 	    h = (tn3270e_header *)obptr;
3437 	    h->data_type = TN3270E_DT_BIND_IMAGE;
3438 	    h->request_flag = 0;
3439 	    h->response_flag = 0;
3440 	    h->seq_number[0] = 0;
3441 	    h->seq_number[1] = 0;
3442 	    obptr += EH_SIZE;
3443 	    for (i = 0; i < bind_image_len; i++) {
3444 		if (bind_image[i] == 0xff) {
3445 		    *obptr++ = 0xff;
3446 		}
3447 		*obptr++ = bind_image[i];
3448 	    }
3449 	    *obptr++ = IAC;
3450 	    *obptr++ = EOR;
3451 	}
3452     }
3453     return any;
3454 }
3455 
3456 /*
3457  * Set blocking/non-blocking mode on the socket.  On error, pops up an error
3458  * message, but does not close the socket.
3459  */
3460 static int
non_blocking(bool on)3461 non_blocking(bool on)
3462 {
3463 #if !defined(BLOCKING_CONNECT_ONLY) /*[*/
3464 # if defined(FIONBIO) /*[*/
3465     IOCTL_T i = on? 1: 0;
3466 
3467     vtrace("Making host socket %sblocking\n", on? "non-": "");
3468     if (sock == INVALID_SOCKET) {
3469 	return 0;
3470     }
3471 
3472     if (SOCK_IOCTL(sock, FIONBIO, &i) < 0) {
3473 	popup_a_sockerr("ioctl(FIONBIO, %d)", on);
3474 	return -1;
3475     }
3476 # else /*][*/
3477     int f;
3478 
3479     vtrace("Making host socket %sblocking\n", on? "non-": "");
3480     if (sock == INVALID_SOCKET) {
3481 	return 0;
3482     }
3483 
3484     if ((f = fcntl(sock, F_GETFL, 0)) == -1) {
3485 	connect_errno(errno, "fcntl(F_GETFL)");
3486 	return -1;
3487     }
3488     if (on) {
3489 	f |= O_NDELAY;
3490     } else {
3491 	f &= ~O_NDELAY;
3492     }
3493     if (fcntl(sock, F_SETFL, f) < 0) {
3494 	connect_errno(errno, "fcntl(F_SETFL)");
3495 	return -1;
3496     }
3497 # endif /*]*/
3498 #endif /*]*/
3499     return 0;
3500 }
3501 
3502 /* Continue TLS negotiation in response to a STARTTLS. */
3503 static void
net_starttls_continue(void)3504 net_starttls_continue(void)
3505 {
3506     sio_negotiate_ret_t ret;
3507     bool data = false;
3508     char *session, *cert;
3509 
3510     /* Negotiate the session. */
3511     ret = sio_negotiate(sio, sock, hostname, &data);
3512     if (ret == SIG_FAILURE) {
3513 	connect_error("%s", sio_last_error());
3514 	host_disconnect(true);
3515 	return;
3516     }
3517     if (ret == SIG_WANTMORE) {
3518 	vtrace("Need more TLS data\n");
3519 	if (starttls_pending == NOT_CONNECTED) {
3520 	    starttls_pending = cstate;
3521 	    change_cstate(TLS_PENDING, "net_starttls_continue");
3522 	}
3523 	return;
3524     }
3525 
3526     secure_connection = true;
3527 
3528     /* Success. */
3529     session = indent_s(sio_session_info(sio));
3530     cert = indent_s(sio_server_cert_info(sio));
3531     vtrace("TLS negotiated connection complete. "
3532 	    "Connection is now secure.\n"
3533 	    "Provider: %s\n"
3534 	    "Session:\n%s\nServer certificate:\n%s\n",
3535 	    sio_provider(), session, cert);
3536     Free(session);
3537     Free(cert);
3538     st_changed(ST_SECURE, true);
3539 
3540     if (starttls_pending == TELNET_PENDING) {
3541 	/*
3542 	 * TLS negotiation happened before 3270 negotiation (which is the usual
3543 	 * case).  Tell the world that we are (still) connected, now in secure
3544 	 * mode.
3545 	 */
3546 	host_connected();
3547     } else {
3548 	/*
3549 	 * The host negotiated TLS while in some other state. Try to restore
3550 	 * it.
3551 	 */
3552 	if (cHALF_CONNECTED(starttls_pending)) {
3553 	    st_changed(ST_NEGOTIATING, true);
3554 	} else {
3555 	    st_changed(ST_3270_MODE, true);
3556 	}
3557     }
3558     starttls_pending = NOT_CONNECTED;
3559 
3560     if (data) {
3561 	/* Got extra data with the negotiation. */
3562 	vtrace("Reading extra data after negotiation\n");
3563 	net_input(INVALID_IOSRC, NULL_IOID);
3564     }
3565 }
3566 
3567 /* Process a STARTTLS subnegotiation. */
3568 static void
continue_tls(unsigned char * sbbuf,int len)3569 continue_tls(unsigned char *sbbuf, int len)
3570 {
3571     /* Whatever happens, we're not expecting another SB STARTTLS. */
3572     need_tls_follows = false;
3573 
3574     /* Make sure the option is FOLLOWS. */
3575     if (len < 2 || sbbuf[1] != TLS_FOLLOWS) {
3576 	/* Trace the junk. */
3577 	vtrace("%s ? %s\n", opt(TELOPT_STARTTLS), cmd(SE));
3578 	connect_error("TLS negotiation failure");
3579 	host_disconnect(true);
3580 	return;
3581     }
3582 
3583     /* Trace what we got. */
3584     vtrace("%s FOLLOWS %s\n", opt(TELOPT_STARTTLS), cmd(SE));
3585 
3586     /* Negotiate. */
3587     net_starttls_continue();
3588 }
3589 
3590 /* Return the current BIND application name, if any. */
3591 const char *
net_query_bind_plu_name(void)3592 net_query_bind_plu_name(void)
3593 {
3594     /*
3595      * Return the PLU name, if we're in TN3270E 3270 mode and have
3596      * negotiated the BIND-IMAGE option.
3597      */
3598     if ((cstate == CONNECTED_TN3270E) &&
3599 	    b8_bit_is_set(&e_funcs, TN3270E_FUNC_BIND_IMAGE)) {
3600 	return plu_name? plu_name: "";
3601     } else {
3602 	return "";
3603     }
3604 }
3605 
3606 /* Return the current connection state. */
3607 const char *
net_query_connection_state(void)3608 net_query_connection_state(void)
3609 {
3610     return state_name[cstate];
3611 }
3612 
3613 /* Return the LU name. */
3614 const char *
net_query_lu_name(void)3615 net_query_lu_name(void)
3616 {
3617     if (CONNECTED && connected_lu != NULL) {
3618 	return connected_lu;
3619     } else {
3620 	return "";
3621     }
3622 }
3623 
3624 /* Return the hostname and port. */
3625 const char *
net_query_host(void)3626 net_query_host(void)
3627 {
3628     if (CONNECTED) {
3629 #if defined(LOCAL_PROCESS) /*[*/
3630 	if (local_process) {
3631 	    return lazyaf("process %s", hostname);
3632 	}
3633 #endif /*]*/
3634 	return lazyaf("host %s %u", hostname, current_port);
3635     } else {
3636 	return "";
3637     }
3638 }
3639 
3640 /* Return the TLS state. */
3641 const char *
net_query_tls(void)3642 net_query_tls(void)
3643 {
3644     static char *not_secure = "not secure";
3645 
3646     if (CONNECTED) {
3647 	if (!secure_connection) {
3648 	    return not_secure;
3649 	}
3650 	return lazyaf("secure %s",
3651 		net_secure_unverified()? "host-unverified": "host-verified");
3652     } else {
3653 	return "";
3654     }
3655 }
3656 
3657 /* Return the local address for the socket. */
3658 int
net_getsockname(void * buf,int * len)3659 net_getsockname(void *buf, int *len)
3660 {
3661     if (sock == INVALID_SOCKET) {
3662 	return -1;
3663     }
3664     return getsockname(sock, buf, (socklen_t *)(void *)len);
3665 }
3666 
3667 /* Return a text version of the current proxy type, or NULL. */
3668 const char *
net_proxy_type(void)3669 net_proxy_type(void)
3670 {
3671     if (proxy_type != PT_NONE) {
3672 	return proxy_type_name(proxy_type);
3673     } else {
3674 	return NULL;
3675     }
3676 }
3677 
3678 /* Return the current proxy user, or NULL. */
3679 const char *
net_proxy_user(void)3680 net_proxy_user(void)
3681 {
3682     if (proxy_type != PT_NONE) {
3683 	return proxy_user;
3684     } else {
3685 	return NULL;
3686     }
3687 }
3688 
3689 /* Return the current proxy host, or NULL. */
3690 const char *
net_proxy_host(void)3691 net_proxy_host(void)
3692 {
3693     if (proxy_type != PT_NONE) {
3694 	return proxy_host;
3695     } else {
3696 	return NULL;
3697     }
3698 }
3699 
3700 /* Return the current proxy port, or NULL. */
3701 const char *
net_proxy_port(void)3702 net_proxy_port(void)
3703 {
3704     if (proxy_type != PT_NONE) {
3705 	return proxy_portname;
3706     } else {
3707 	return NULL;
3708     }
3709 }
3710 
3711 /* Return the SNA binding state. */
3712 bool
net_bound(void)3713 net_bound(void)
3714 {
3715     return (IN_E && tn3270e_bound);
3716 }
3717 
3718 /* Format TELNET options. */
3719 static const char *
net_opts(unsigned char opts[])3720 net_opts(unsigned char opts[])
3721 {
3722     int i;
3723     char *ret = NULL;
3724     size_t sl = 0;
3725 
3726     for (i = 0; i < N_OPTS; i++) {
3727 	if (opts[i]) {
3728 	    const char *o = opt(i);
3729 
3730 	    ret = (char *)Realloc(ret, sl + 1 + strlen(o) + 1);
3731 	    if (sl) {
3732 		ret[sl++] = ' ';
3733 	    }
3734 	    strcpy(ret + sl, o);
3735 	    sl += strlen(o);
3736 	}
3737     }
3738     return ret;
3739 }
3740 
3741 /* Return my TELNET options. */
3742 const char *
net_myopts(void)3743 net_myopts(void)
3744 {
3745     return net_opts(myopts);
3746 }
3747 
3748 /* Return his TELNET options. */
3749 const char *
net_hisopts(void)3750 net_hisopts(void)
3751 {
3752     return net_opts(hisopts);
3753 }
3754 
3755 /*
3756  * Set the default termtype.
3757  *
3758  * This is called at init time, whenever we disconnect, and whenever the screen
3759  * dimensions change (which by definition happens while we are disconnected).
3760  * It sets 'termtype' to the default value, assuming an extended data stream
3761  * host. When we connect to a particular host, we may use a different value
3762  * (such as without the -E, for the S: prefix).
3763  */
3764 void
net_set_default_termtype(void)3765 net_set_default_termtype(void)
3766 {
3767     if (appres.termname) {
3768 	termtype = appres.termname;
3769     } else if (appres.nvt_mode || HOST_FLAG(ANSI_HOST)) {
3770 	termtype = "xterm";
3771     } else if (ov_rows || ov_cols) {
3772 	termtype = "IBM-DYNAMIC";
3773     } else if (HOST_FLAG(STD_DS_HOST)) {
3774 	snprintf(ttype_tmpval, sizeof(ttype_tmpval), "IBM-327%c-%d",
3775 		mode.m3279? '9': '8', model_num);
3776 	termtype = ttype_tmpval;
3777     } else {
3778 	termtype = full_model_name;
3779     }
3780 
3781     st_changed(ST_TERMINAL_NAME, true);
3782 }
3783 
3784 /* Handle an ST_REMODEL indication. */
3785 static void
net_remodel(bool ignored _is_unused)3786 net_remodel(bool ignored _is_unused)
3787 {
3788     net_set_default_termtype();
3789 }
3790 
3791 bool
net_secure_unverified(void)3792 net_secure_unverified(void)
3793 {
3794     return secure_connection && sio_secure_unverified(sio);
3795 }
3796 
3797 const char *
net_session_info(void)3798 net_session_info(void)
3799 {
3800     if (sio == NULL) {
3801 	return NULL;
3802     }
3803     return sio_session_info(sio);
3804 }
3805 
3806 const char *
net_server_cert_info(void)3807 net_server_cert_info(void)
3808 {
3809     if (sio == NULL) {
3810 	return NULL;
3811     }
3812     return sio_server_cert_info(sio);
3813 }
3814 
3815 bool
net_secure_connection(void)3816 net_secure_connection(void)
3817 {
3818     return secure_connection;
3819 }
3820 
3821 unsigned
net_sio_supported(void)3822 net_sio_supported(void)
3823 {
3824     return sio_supported();
3825 }
3826 
3827 const char *
net_sio_provider(void)3828 net_sio_provider(void)
3829 {
3830     return sio_provider();
3831 }
3832 
3833 /*
3834  * Change the NOP transmit interval.
3835  */
3836 void
net_nop_seconds(void)3837 net_nop_seconds(void)
3838 {
3839     /* Cancel first. */
3840     if (nop_timeout_id != NULL_IOID) {
3841 	RemoveTimeOut(nop_timeout_id);
3842 	nop_timeout_id = NULL_IOID;
3843     }
3844 
3845     if (appres.nop_seconds == 0) {
3846 	return;
3847     }
3848 
3849     /* Restart with the new interval. */
3850     if (cstate >= TELNET_PENDING) {
3851 	nop_timeout_id = AddTimeOut(appres.nop_seconds * 1000, send_nop);
3852     }
3853 }
3854 
3855 /* Break NVT data tracing. */
3856 void
net_nvt_break(void)3857 net_nvt_break(void)
3858 {
3859     if (nvt_data) {
3860 	vtrace("\n");
3861 	nvt_data = 0;
3862     }
3863 }
3864 
3865 /* Module registration. */
3866 void
net_register(void)3867 net_register(void)
3868 {
3869     /* Register for state changes. */
3870     register_schange(ST_REMODEL, net_remodel);
3871 }
3872