xref: /freebsd/crypto/openssh/ttymodes.c (revision d95e11bf7e5a59b5c3f81bd8dfc2918ee7d3bada)
1511b41d2SMark Murray /*
2511b41d2SMark Murray  * Author: Tatu Ylonen <ylo@cs.hut.fi>
3511b41d2SMark Murray  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4511b41d2SMark Murray  *                    All rights reserved
5b66f2d16SKris Kennaway  *
6b66f2d16SKris Kennaway  * As far as I am concerned, the code I have written for this software
7b66f2d16SKris Kennaway  * can be used freely for any purpose.  Any derived versions of this
8b66f2d16SKris Kennaway  * software must be clearly marked as such, and if the derived work is
9b66f2d16SKris Kennaway  * incompatible with the protocol description in the RFC file, it must be
10b66f2d16SKris Kennaway  * called by a name other than "ssh" or "Secure Shell".
11511b41d2SMark Murray  */
12511b41d2SMark Murray 
131e8db6e2SBrian Feldman /*
141e8db6e2SBrian Feldman  * SSH2 tty modes support by Kevin Steves.
151e8db6e2SBrian Feldman  * Copyright (c) 2001 Kevin Steves.  All rights reserved.
161e8db6e2SBrian Feldman  *
171e8db6e2SBrian Feldman  * Redistribution and use in source and binary forms, with or without
181e8db6e2SBrian Feldman  * modification, are permitted provided that the following conditions
191e8db6e2SBrian Feldman  * are met:
201e8db6e2SBrian Feldman  * 1. Redistributions of source code must retain the above copyright
211e8db6e2SBrian Feldman  *    notice, this list of conditions and the following disclaimer.
221e8db6e2SBrian Feldman  * 2. Redistributions in binary form must reproduce the above copyright
231e8db6e2SBrian Feldman  *    notice, this list of conditions and the following disclaimer in the
241e8db6e2SBrian Feldman  *    documentation and/or other materials provided with the distribution.
251e8db6e2SBrian Feldman  *
261e8db6e2SBrian Feldman  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
271e8db6e2SBrian Feldman  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
281e8db6e2SBrian Feldman  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
291e8db6e2SBrian Feldman  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
301e8db6e2SBrian Feldman  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
311e8db6e2SBrian Feldman  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
321e8db6e2SBrian Feldman  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
331e8db6e2SBrian Feldman  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
341e8db6e2SBrian Feldman  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
351e8db6e2SBrian Feldman  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
361e8db6e2SBrian Feldman  */
371e8db6e2SBrian Feldman 
381e8db6e2SBrian Feldman /*
391e8db6e2SBrian Feldman  * Encoding and decoding of terminal modes in a portable way.
401e8db6e2SBrian Feldman  * Much of the format is defined in ttymodes.h; it is included multiple times
411e8db6e2SBrian Feldman  * into this file with the appropriate macro definitions to generate the
421e8db6e2SBrian Feldman  * suitable code.
431e8db6e2SBrian Feldman  */
441e8db6e2SBrian Feldman 
45511b41d2SMark Murray #include "includes.h"
46d95e11bfSDag-Erling Smørgrav RCSID("$OpenBSD: ttymodes.c,v 1.19 2003/04/08 20:21:29 itojun Exp $");
47511b41d2SMark Murray 
48511b41d2SMark Murray #include "packet.h"
491e8db6e2SBrian Feldman #include "log.h"
501e8db6e2SBrian Feldman #include "ssh1.h"
511e8db6e2SBrian Feldman #include "compat.h"
521e8db6e2SBrian Feldman #include "buffer.h"
531e8db6e2SBrian Feldman #include "bufaux.h"
54511b41d2SMark Murray 
55511b41d2SMark Murray #define TTY_OP_END		0
561e8db6e2SBrian Feldman /*
571e8db6e2SBrian Feldman  * uint32 (u_int) follows speed in SSH1 and SSH2
581e8db6e2SBrian Feldman  */
591e8db6e2SBrian Feldman #define TTY_OP_ISPEED_PROTO1	192
601e8db6e2SBrian Feldman #define TTY_OP_OSPEED_PROTO1	193
611e8db6e2SBrian Feldman #define TTY_OP_ISPEED_PROTO2	128
621e8db6e2SBrian Feldman #define TTY_OP_OSPEED_PROTO2	129
63511b41d2SMark Murray 
64511b41d2SMark Murray /*
65511b41d2SMark Murray  * Converts POSIX speed_t to a baud rate.  The values of the
66511b41d2SMark Murray  * constants for speed_t are not themselves portable.
67511b41d2SMark Murray  */
68511b41d2SMark Murray static int
69511b41d2SMark Murray speed_to_baud(speed_t speed)
70511b41d2SMark Murray {
71511b41d2SMark Murray 	switch (speed) {
72511b41d2SMark Murray 	case B0:
73511b41d2SMark Murray 		return 0;
74511b41d2SMark Murray 	case B50:
75511b41d2SMark Murray 		return 50;
76511b41d2SMark Murray 	case B75:
77511b41d2SMark Murray 		return 75;
78511b41d2SMark Murray 	case B110:
79511b41d2SMark Murray 		return 110;
80511b41d2SMark Murray 	case B134:
81511b41d2SMark Murray 		return 134;
82511b41d2SMark Murray 	case B150:
83511b41d2SMark Murray 		return 150;
84511b41d2SMark Murray 	case B200:
85511b41d2SMark Murray 		return 200;
86511b41d2SMark Murray 	case B300:
87511b41d2SMark Murray 		return 300;
88511b41d2SMark Murray 	case B600:
89511b41d2SMark Murray 		return 600;
90511b41d2SMark Murray 	case B1200:
91511b41d2SMark Murray 		return 1200;
92511b41d2SMark Murray 	case B1800:
93511b41d2SMark Murray 		return 1800;
94511b41d2SMark Murray 	case B2400:
95511b41d2SMark Murray 		return 2400;
96511b41d2SMark Murray 	case B4800:
97511b41d2SMark Murray 		return 4800;
98511b41d2SMark Murray 	case B9600:
99511b41d2SMark Murray 		return 9600;
100511b41d2SMark Murray 
101511b41d2SMark Murray #ifdef B19200
102511b41d2SMark Murray 	case B19200:
103511b41d2SMark Murray 		return 19200;
104511b41d2SMark Murray #else /* B19200 */
105511b41d2SMark Murray #ifdef EXTA
106511b41d2SMark Murray 	case EXTA:
107511b41d2SMark Murray 		return 19200;
108511b41d2SMark Murray #endif /* EXTA */
109511b41d2SMark Murray #endif /* B19200 */
110511b41d2SMark Murray 
111511b41d2SMark Murray #ifdef B38400
112511b41d2SMark Murray 	case B38400:
113511b41d2SMark Murray 		return 38400;
114511b41d2SMark Murray #else /* B38400 */
115511b41d2SMark Murray #ifdef EXTB
116511b41d2SMark Murray 	case EXTB:
117511b41d2SMark Murray 		return 38400;
118511b41d2SMark Murray #endif /* EXTB */
119511b41d2SMark Murray #endif /* B38400 */
120511b41d2SMark Murray 
121511b41d2SMark Murray #ifdef B7200
122511b41d2SMark Murray 	case B7200:
123511b41d2SMark Murray 		return 7200;
124511b41d2SMark Murray #endif /* B7200 */
125511b41d2SMark Murray #ifdef B14400
126511b41d2SMark Murray 	case B14400:
127511b41d2SMark Murray 		return 14400;
128511b41d2SMark Murray #endif /* B14400 */
129511b41d2SMark Murray #ifdef B28800
130511b41d2SMark Murray 	case B28800:
131511b41d2SMark Murray 		return 28800;
132511b41d2SMark Murray #endif /* B28800 */
133511b41d2SMark Murray #ifdef B57600
134511b41d2SMark Murray 	case B57600:
135511b41d2SMark Murray 		return 57600;
136511b41d2SMark Murray #endif /* B57600 */
137511b41d2SMark Murray #ifdef B76800
138511b41d2SMark Murray 	case B76800:
139511b41d2SMark Murray 		return 76800;
140511b41d2SMark Murray #endif /* B76800 */
141511b41d2SMark Murray #ifdef B115200
142511b41d2SMark Murray 	case B115200:
143511b41d2SMark Murray 		return 115200;
144511b41d2SMark Murray #endif /* B115200 */
145511b41d2SMark Murray #ifdef B230400
146511b41d2SMark Murray 	case B230400:
147511b41d2SMark Murray 		return 230400;
148511b41d2SMark Murray #endif /* B230400 */
149511b41d2SMark Murray 	default:
150511b41d2SMark Murray 		return 9600;
151511b41d2SMark Murray 	}
152511b41d2SMark Murray }
153511b41d2SMark Murray 
154511b41d2SMark Murray /*
155511b41d2SMark Murray  * Converts a numeric baud rate to a POSIX speed_t.
156511b41d2SMark Murray  */
157511b41d2SMark Murray static speed_t
158511b41d2SMark Murray baud_to_speed(int baud)
159511b41d2SMark Murray {
160511b41d2SMark Murray 	switch (baud) {
161511b41d2SMark Murray 	case 0:
162511b41d2SMark Murray 		return B0;
163511b41d2SMark Murray 	case 50:
164511b41d2SMark Murray 		return B50;
165511b41d2SMark Murray 	case 75:
166511b41d2SMark Murray 		return B75;
167511b41d2SMark Murray 	case 110:
168511b41d2SMark Murray 		return B110;
169511b41d2SMark Murray 	case 134:
170511b41d2SMark Murray 		return B134;
171511b41d2SMark Murray 	case 150:
172511b41d2SMark Murray 		return B150;
173511b41d2SMark Murray 	case 200:
174511b41d2SMark Murray 		return B200;
175511b41d2SMark Murray 	case 300:
176511b41d2SMark Murray 		return B300;
177511b41d2SMark Murray 	case 600:
178511b41d2SMark Murray 		return B600;
179511b41d2SMark Murray 	case 1200:
180511b41d2SMark Murray 		return B1200;
181511b41d2SMark Murray 	case 1800:
182511b41d2SMark Murray 		return B1800;
183511b41d2SMark Murray 	case 2400:
184511b41d2SMark Murray 		return B2400;
185511b41d2SMark Murray 	case 4800:
186511b41d2SMark Murray 		return B4800;
187511b41d2SMark Murray 	case 9600:
188511b41d2SMark Murray 		return B9600;
189511b41d2SMark Murray 
190511b41d2SMark Murray #ifdef B19200
191511b41d2SMark Murray 	case 19200:
192511b41d2SMark Murray 		return B19200;
193511b41d2SMark Murray #else /* B19200 */
194511b41d2SMark Murray #ifdef EXTA
195511b41d2SMark Murray 	case 19200:
196511b41d2SMark Murray 		return EXTA;
197511b41d2SMark Murray #endif /* EXTA */
198511b41d2SMark Murray #endif /* B19200 */
199511b41d2SMark Murray 
200511b41d2SMark Murray #ifdef B38400
201511b41d2SMark Murray 	case 38400:
202511b41d2SMark Murray 		return B38400;
203511b41d2SMark Murray #else /* B38400 */
204511b41d2SMark Murray #ifdef EXTB
205511b41d2SMark Murray 	case 38400:
206511b41d2SMark Murray 		return EXTB;
207511b41d2SMark Murray #endif /* EXTB */
208511b41d2SMark Murray #endif /* B38400 */
209511b41d2SMark Murray 
210511b41d2SMark Murray #ifdef B7200
211511b41d2SMark Murray 	case 7200:
212511b41d2SMark Murray 		return B7200;
213511b41d2SMark Murray #endif /* B7200 */
214511b41d2SMark Murray #ifdef B14400
215511b41d2SMark Murray 	case 14400:
216511b41d2SMark Murray 		return B14400;
217511b41d2SMark Murray #endif /* B14400 */
218511b41d2SMark Murray #ifdef B28800
219511b41d2SMark Murray 	case 28800:
220511b41d2SMark Murray 		return B28800;
221511b41d2SMark Murray #endif /* B28800 */
222511b41d2SMark Murray #ifdef B57600
223511b41d2SMark Murray 	case 57600:
224511b41d2SMark Murray 		return B57600;
225511b41d2SMark Murray #endif /* B57600 */
226511b41d2SMark Murray #ifdef B76800
227511b41d2SMark Murray 	case 76800:
228511b41d2SMark Murray 		return B76800;
229511b41d2SMark Murray #endif /* B76800 */
230511b41d2SMark Murray #ifdef B115200
231511b41d2SMark Murray 	case 115200:
232511b41d2SMark Murray 		return B115200;
233511b41d2SMark Murray #endif /* B115200 */
234511b41d2SMark Murray #ifdef B230400
235511b41d2SMark Murray 	case 230400:
236511b41d2SMark Murray 		return B230400;
237511b41d2SMark Murray #endif /* B230400 */
238511b41d2SMark Murray 	default:
239511b41d2SMark Murray 		return B9600;
240511b41d2SMark Murray 	}
241511b41d2SMark Murray }
242511b41d2SMark Murray 
243511b41d2SMark Murray /*
244511b41d2SMark Murray  * Encodes terminal modes for the terminal referenced by fd
2451e8db6e2SBrian Feldman  * or tiop in a portable manner, and appends the modes to a packet
246511b41d2SMark Murray  * being constructed.
247511b41d2SMark Murray  */
248511b41d2SMark Murray void
2491e8db6e2SBrian Feldman tty_make_modes(int fd, struct termios *tiop)
250511b41d2SMark Murray {
251511b41d2SMark Murray 	struct termios tio;
252511b41d2SMark Murray 	int baud;
2531e8db6e2SBrian Feldman 	Buffer buf;
2541e8db6e2SBrian Feldman 	int tty_op_ospeed, tty_op_ispeed;
2551e8db6e2SBrian Feldman 	void (*put_arg)(Buffer *, u_int);
256511b41d2SMark Murray 
2571e8db6e2SBrian Feldman 	buffer_init(&buf);
2581e8db6e2SBrian Feldman 	if (compat20) {
2591e8db6e2SBrian Feldman 		tty_op_ospeed = TTY_OP_OSPEED_PROTO2;
2601e8db6e2SBrian Feldman 		tty_op_ispeed = TTY_OP_ISPEED_PROTO2;
2611e8db6e2SBrian Feldman 		put_arg = buffer_put_int;
2621e8db6e2SBrian Feldman 	} else {
2631e8db6e2SBrian Feldman 		tty_op_ospeed = TTY_OP_OSPEED_PROTO1;
2641e8db6e2SBrian Feldman 		tty_op_ispeed = TTY_OP_ISPEED_PROTO1;
2651e8db6e2SBrian Feldman 		put_arg = (void (*)(Buffer *, u_int)) buffer_put_char;
266511b41d2SMark Murray 	}
2671e8db6e2SBrian Feldman 
2681e8db6e2SBrian Feldman 	if (tiop == NULL) {
2691e8db6e2SBrian Feldman 		if (tcgetattr(fd, &tio) == -1) {
270d95e11bfSDag-Erling Smørgrav 			logit("tcgetattr: %.100s", strerror(errno));
2711e8db6e2SBrian Feldman 			goto end;
2721e8db6e2SBrian Feldman 		}
2731e8db6e2SBrian Feldman 	} else
2741e8db6e2SBrian Feldman 		tio = *tiop;
2751e8db6e2SBrian Feldman 
276511b41d2SMark Murray 	/* Store input and output baud rates. */
277511b41d2SMark Murray 	baud = speed_to_baud(cfgetospeed(&tio));
278ae1f160dSDag-Erling Smørgrav 	debug3("tty_make_modes: ospeed %d", baud);
2791e8db6e2SBrian Feldman 	buffer_put_char(&buf, tty_op_ospeed);
2801e8db6e2SBrian Feldman 	buffer_put_int(&buf, baud);
281511b41d2SMark Murray 	baud = speed_to_baud(cfgetispeed(&tio));
282ae1f160dSDag-Erling Smørgrav 	debug3("tty_make_modes: ispeed %d", baud);
2831e8db6e2SBrian Feldman 	buffer_put_char(&buf, tty_op_ispeed);
2841e8db6e2SBrian Feldman 	buffer_put_int(&buf, baud);
285511b41d2SMark Murray 
286511b41d2SMark Murray 	/* Store values of mode flags. */
287511b41d2SMark Murray #define TTYCHAR(NAME, OP) \
288ae1f160dSDag-Erling Smørgrav 	debug3("tty_make_modes: %d %d", OP, tio.c_cc[NAME]); \
2891e8db6e2SBrian Feldman 	buffer_put_char(&buf, OP); \
2901e8db6e2SBrian Feldman 	put_arg(&buf, tio.c_cc[NAME]);
2911e8db6e2SBrian Feldman 
292511b41d2SMark Murray #define TTYMODE(NAME, FIELD, OP) \
293ae1f160dSDag-Erling Smørgrav 	debug3("tty_make_modes: %d %d", OP, ((tio.FIELD & NAME) != 0)); \
2941e8db6e2SBrian Feldman 	buffer_put_char(&buf, OP); \
2951e8db6e2SBrian Feldman 	put_arg(&buf, ((tio.FIELD & NAME) != 0));
296511b41d2SMark Murray 
297511b41d2SMark Murray #include "ttymodes.h"
298511b41d2SMark Murray 
299511b41d2SMark Murray #undef TTYCHAR
300511b41d2SMark Murray #undef TTYMODE
301511b41d2SMark Murray 
3021e8db6e2SBrian Feldman end:
303511b41d2SMark Murray 	/* Mark end of mode data. */
3041e8db6e2SBrian Feldman 	buffer_put_char(&buf, TTY_OP_END);
3051e8db6e2SBrian Feldman 	if (compat20)
3061e8db6e2SBrian Feldman 		packet_put_string(buffer_ptr(&buf), buffer_len(&buf));
3071e8db6e2SBrian Feldman 	else
3081e8db6e2SBrian Feldman 		packet_put_raw(buffer_ptr(&buf), buffer_len(&buf));
3091e8db6e2SBrian Feldman 	buffer_free(&buf);
310511b41d2SMark Murray }
311511b41d2SMark Murray 
312511b41d2SMark Murray /*
313511b41d2SMark Murray  * Decodes terminal modes for the terminal referenced by fd in a portable
314511b41d2SMark Murray  * manner from a packet being read.
315511b41d2SMark Murray  */
316511b41d2SMark Murray void
317511b41d2SMark Murray tty_parse_modes(int fd, int *n_bytes_ptr)
318511b41d2SMark Murray {
319511b41d2SMark Murray 	struct termios tio;
320511b41d2SMark Murray 	int opcode, baud;
321511b41d2SMark Murray 	int n_bytes = 0;
322511b41d2SMark Murray 	int failure = 0;
3231e8db6e2SBrian Feldman 	u_int (*get_arg)(void);
3241e8db6e2SBrian Feldman 	int arg, arg_size;
3251e8db6e2SBrian Feldman 
3261e8db6e2SBrian Feldman 	if (compat20) {
3271e8db6e2SBrian Feldman 		*n_bytes_ptr = packet_get_int();
328ae1f160dSDag-Erling Smørgrav 		debug3("tty_parse_modes: SSH2 n_bytes %d", *n_bytes_ptr);
3291e8db6e2SBrian Feldman 		if (*n_bytes_ptr == 0)
3301e8db6e2SBrian Feldman 			return;
3311e8db6e2SBrian Feldman 		get_arg = packet_get_int;
3321e8db6e2SBrian Feldman 		arg_size = 4;
3331e8db6e2SBrian Feldman 	} else {
3341e8db6e2SBrian Feldman 		get_arg = packet_get_char;
3351e8db6e2SBrian Feldman 		arg_size = 1;
3361e8db6e2SBrian Feldman 	}
337511b41d2SMark Murray 
338511b41d2SMark Murray 	/*
339511b41d2SMark Murray 	 * Get old attributes for the terminal.  We will modify these
340511b41d2SMark Murray 	 * flags. I am hoping that if there are any machine-specific
341511b41d2SMark Murray 	 * modes, they will initially have reasonable values.
342511b41d2SMark Murray 	 */
3431e8db6e2SBrian Feldman 	if (tcgetattr(fd, &tio) == -1) {
344d95e11bfSDag-Erling Smørgrav 		logit("tcgetattr: %.100s", strerror(errno));
345511b41d2SMark Murray 		failure = -1;
3461e8db6e2SBrian Feldman 	}
347511b41d2SMark Murray 
348511b41d2SMark Murray 	for (;;) {
349511b41d2SMark Murray 		n_bytes += 1;
350511b41d2SMark Murray 		opcode = packet_get_char();
351511b41d2SMark Murray 		switch (opcode) {
352511b41d2SMark Murray 		case TTY_OP_END:
353511b41d2SMark Murray 			goto set;
354511b41d2SMark Murray 
3551e8db6e2SBrian Feldman 		/* XXX: future conflict possible */
3561e8db6e2SBrian Feldman 		case TTY_OP_ISPEED_PROTO1:
3571e8db6e2SBrian Feldman 		case TTY_OP_ISPEED_PROTO2:
358511b41d2SMark Murray 			n_bytes += 4;
359511b41d2SMark Murray 			baud = packet_get_int();
360ae1f160dSDag-Erling Smørgrav 			debug3("tty_parse_modes: ispeed %d", baud);
3611e8db6e2SBrian Feldman 			if (failure != -1 && cfsetispeed(&tio, baud_to_speed(baud)) == -1)
362511b41d2SMark Murray 				error("cfsetispeed failed for %d", baud);
363511b41d2SMark Murray 			break;
364511b41d2SMark Murray 
3651e8db6e2SBrian Feldman 		/* XXX: future conflict possible */
3661e8db6e2SBrian Feldman 		case TTY_OP_OSPEED_PROTO1:
3671e8db6e2SBrian Feldman 		case TTY_OP_OSPEED_PROTO2:
368511b41d2SMark Murray 			n_bytes += 4;
369511b41d2SMark Murray 			baud = packet_get_int();
370ae1f160dSDag-Erling Smørgrav 			debug3("tty_parse_modes: ospeed %d", baud);
3711e8db6e2SBrian Feldman 			if (failure != -1 && cfsetospeed(&tio, baud_to_speed(baud)) == -1)
372511b41d2SMark Murray 				error("cfsetospeed failed for %d", baud);
373511b41d2SMark Murray 			break;
374511b41d2SMark Murray 
375511b41d2SMark Murray #define TTYCHAR(NAME, OP) \
376511b41d2SMark Murray 	case OP: \
3771e8db6e2SBrian Feldman 	  n_bytes += arg_size; \
3781e8db6e2SBrian Feldman 	  tio.c_cc[NAME] = get_arg(); \
379ae1f160dSDag-Erling Smørgrav 	  debug3("tty_parse_modes: %d %d", OP, tio.c_cc[NAME]); \
380511b41d2SMark Murray 	  break;
381511b41d2SMark Murray #define TTYMODE(NAME, FIELD, OP) \
382511b41d2SMark Murray 	case OP: \
3831e8db6e2SBrian Feldman 	  n_bytes += arg_size; \
3841e8db6e2SBrian Feldman 	  if ((arg = get_arg())) \
385511b41d2SMark Murray 	    tio.FIELD |= NAME; \
386511b41d2SMark Murray 	  else \
387511b41d2SMark Murray 	    tio.FIELD &= ~NAME;	\
388ae1f160dSDag-Erling Smørgrav 	  debug3("tty_parse_modes: %d %d", OP, arg); \
389511b41d2SMark Murray 	  break;
390511b41d2SMark Murray 
391511b41d2SMark Murray #include "ttymodes.h"
392511b41d2SMark Murray 
393511b41d2SMark Murray #undef TTYCHAR
394511b41d2SMark Murray #undef TTYMODE
395511b41d2SMark Murray 
396511b41d2SMark Murray 		default:
397511b41d2SMark Murray 			debug("Ignoring unsupported tty mode opcode %d (0x%x)",
398511b41d2SMark Murray 			    opcode, opcode);
3991e8db6e2SBrian Feldman 			if (!compat20) {
400511b41d2SMark Murray 				/*
4011e8db6e2SBrian Feldman 				 * SSH1:
4021e8db6e2SBrian Feldman 				 * Opcodes 1 to 127 are defined to have
403511b41d2SMark Murray 				 * a one-byte argument.
404511b41d2SMark Murray 				 * Opcodes 128 to 159 are defined to have
405511b41d2SMark Murray 				 * an integer argument.
406511b41d2SMark Murray 				 */
4071e8db6e2SBrian Feldman 				if (opcode > 0 && opcode < 128) {
4081e8db6e2SBrian Feldman 					n_bytes += 1;
4091e8db6e2SBrian Feldman 					(void) packet_get_char();
4101e8db6e2SBrian Feldman 					break;
4111e8db6e2SBrian Feldman 				} else if (opcode >= 128 && opcode < 160) {
412511b41d2SMark Murray 					n_bytes += 4;
413511b41d2SMark Murray 					(void) packet_get_int();
414511b41d2SMark Murray 					break;
4151e8db6e2SBrian Feldman 				} else {
416511b41d2SMark Murray 					/*
417511b41d2SMark Murray 					 * It is a truly undefined opcode (160 to 255).
418511b41d2SMark Murray 					 * We have no idea about its arguments.  So we
419511b41d2SMark Murray 					 * must stop parsing.  Note that some data may be
420511b41d2SMark Murray 					 * left in the packet; hopefully there is nothing
421511b41d2SMark Murray 					 * more coming after the mode data.
422511b41d2SMark Murray 					 */
423d95e11bfSDag-Erling Smørgrav 					logit("parse_tty_modes: unknown opcode %d", opcode);
424511b41d2SMark Murray 					goto set;
425511b41d2SMark Murray 				}
4261e8db6e2SBrian Feldman 			} else {
4271e8db6e2SBrian Feldman 				/*
4281e8db6e2SBrian Feldman 				 * SSH2:
4291e8db6e2SBrian Feldman 				 * Opcodes 1 to 159 are defined to have
4301e8db6e2SBrian Feldman 				 * a uint32 argument.
4311e8db6e2SBrian Feldman 				 * Opcodes 160 to 255 are undefined and
4321e8db6e2SBrian Feldman 				 * cause parsing to stop.
4331e8db6e2SBrian Feldman 				 */
4341e8db6e2SBrian Feldman 				if (opcode > 0 && opcode < 160) {
4351e8db6e2SBrian Feldman 					n_bytes += 4;
4361e8db6e2SBrian Feldman 					(void) packet_get_int();
4371e8db6e2SBrian Feldman 					break;
4381e8db6e2SBrian Feldman 				} else {
439d95e11bfSDag-Erling Smørgrav 					logit("parse_tty_modes: unknown opcode %d", opcode);
4401e8db6e2SBrian Feldman 					goto set;
4411e8db6e2SBrian Feldman 				}
4421e8db6e2SBrian Feldman 			}
4431e8db6e2SBrian Feldman 		}
444511b41d2SMark Murray 	}
445511b41d2SMark Murray 
446511b41d2SMark Murray set:
447511b41d2SMark Murray 	if (*n_bytes_ptr != n_bytes) {
448511b41d2SMark Murray 		*n_bytes_ptr = n_bytes;
449d95e11bfSDag-Erling Smørgrav 		logit("parse_tty_modes: n_bytes_ptr != n_bytes: %d %d",
4501e8db6e2SBrian Feldman 		    *n_bytes_ptr, n_bytes);
451511b41d2SMark Murray 		return;		/* Don't process bytes passed */
452511b41d2SMark Murray 	}
453511b41d2SMark Murray 	if (failure == -1)
4541e8db6e2SBrian Feldman 		return;		/* Packet parsed ok but tcgetattr() failed */
455511b41d2SMark Murray 
456511b41d2SMark Murray 	/* Set the new modes for the terminal. */
4571e8db6e2SBrian Feldman 	if (tcsetattr(fd, TCSANOW, &tio) == -1)
458d95e11bfSDag-Erling Smørgrav 		logit("Setting tty modes failed: %.100s", strerror(errno));
459511b41d2SMark Murray }
460