xref: /freebsd/crypto/openssh/ttymodes.c (revision 4f52dfbb8d6c4d446500c5b097e3806ec219fbd4)
1*4f52dfbbSDag-Erling Smørgrav /* $OpenBSD: ttymodes.c,v 1.32 2017/04/30 23:26:54 djm Exp $ */
2511b41d2SMark Murray /*
3511b41d2SMark Murray  * Author: Tatu Ylonen <ylo@cs.hut.fi>
4511b41d2SMark Murray  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5511b41d2SMark Murray  *                    All rights reserved
6b66f2d16SKris Kennaway  *
7b66f2d16SKris Kennaway  * As far as I am concerned, the code I have written for this software
8b66f2d16SKris Kennaway  * can be used freely for any purpose.  Any derived versions of this
9b66f2d16SKris Kennaway  * software must be clearly marked as such, and if the derived work is
10b66f2d16SKris Kennaway  * incompatible with the protocol description in the RFC file, it must be
11b66f2d16SKris Kennaway  * called by a name other than "ssh" or "Secure Shell".
12511b41d2SMark Murray  */
13511b41d2SMark Murray 
141e8db6e2SBrian Feldman /*
151e8db6e2SBrian Feldman  * SSH2 tty modes support by Kevin Steves.
161e8db6e2SBrian Feldman  * Copyright (c) 2001 Kevin Steves.  All rights reserved.
171e8db6e2SBrian Feldman  *
181e8db6e2SBrian Feldman  * Redistribution and use in source and binary forms, with or without
191e8db6e2SBrian Feldman  * modification, are permitted provided that the following conditions
201e8db6e2SBrian Feldman  * are met:
211e8db6e2SBrian Feldman  * 1. Redistributions of source code must retain the above copyright
221e8db6e2SBrian Feldman  *    notice, this list of conditions and the following disclaimer.
231e8db6e2SBrian Feldman  * 2. Redistributions in binary form must reproduce the above copyright
241e8db6e2SBrian Feldman  *    notice, this list of conditions and the following disclaimer in the
251e8db6e2SBrian Feldman  *    documentation and/or other materials provided with the distribution.
261e8db6e2SBrian Feldman  *
271e8db6e2SBrian Feldman  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
281e8db6e2SBrian Feldman  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
291e8db6e2SBrian Feldman  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
301e8db6e2SBrian Feldman  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
311e8db6e2SBrian Feldman  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
321e8db6e2SBrian Feldman  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
331e8db6e2SBrian Feldman  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
341e8db6e2SBrian Feldman  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
351e8db6e2SBrian Feldman  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
361e8db6e2SBrian Feldman  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
371e8db6e2SBrian Feldman  */
381e8db6e2SBrian Feldman 
391e8db6e2SBrian Feldman /*
401e8db6e2SBrian Feldman  * Encoding and decoding of terminal modes in a portable way.
411e8db6e2SBrian Feldman  * Much of the format is defined in ttymodes.h; it is included multiple times
421e8db6e2SBrian Feldman  * into this file with the appropriate macro definitions to generate the
431e8db6e2SBrian Feldman  * suitable code.
441e8db6e2SBrian Feldman  */
451e8db6e2SBrian Feldman 
46511b41d2SMark Murray #include "includes.h"
47761efaa7SDag-Erling Smørgrav 
48761efaa7SDag-Erling Smørgrav #include <sys/types.h>
49761efaa7SDag-Erling Smørgrav 
50761efaa7SDag-Erling Smørgrav #include <errno.h>
51761efaa7SDag-Erling Smørgrav #include <string.h>
52761efaa7SDag-Erling Smørgrav #include <termios.h>
53761efaa7SDag-Erling Smørgrav #include <stdarg.h>
54511b41d2SMark Murray 
55511b41d2SMark Murray #include "packet.h"
561e8db6e2SBrian Feldman #include "log.h"
571e8db6e2SBrian Feldman #include "compat.h"
581e8db6e2SBrian Feldman #include "buffer.h"
59511b41d2SMark Murray 
60511b41d2SMark Murray #define TTY_OP_END		0
611e8db6e2SBrian Feldman /*
62*4f52dfbbSDag-Erling Smørgrav  * uint32 (u_int) follows speed.
631e8db6e2SBrian Feldman  */
64*4f52dfbbSDag-Erling Smørgrav #define TTY_OP_ISPEED	128
65*4f52dfbbSDag-Erling Smørgrav #define TTY_OP_OSPEED	129
66511b41d2SMark Murray 
67511b41d2SMark Murray /*
68511b41d2SMark Murray  * Converts POSIX speed_t to a baud rate.  The values of the
69511b41d2SMark Murray  * constants for speed_t are not themselves portable.
70511b41d2SMark Murray  */
71511b41d2SMark Murray static int
72511b41d2SMark Murray speed_to_baud(speed_t speed)
73511b41d2SMark Murray {
74511b41d2SMark Murray 	switch (speed) {
75511b41d2SMark Murray 	case B0:
76511b41d2SMark Murray 		return 0;
77511b41d2SMark Murray 	case B50:
78511b41d2SMark Murray 		return 50;
79511b41d2SMark Murray 	case B75:
80511b41d2SMark Murray 		return 75;
81511b41d2SMark Murray 	case B110:
82511b41d2SMark Murray 		return 110;
83511b41d2SMark Murray 	case B134:
84511b41d2SMark Murray 		return 134;
85511b41d2SMark Murray 	case B150:
86511b41d2SMark Murray 		return 150;
87511b41d2SMark Murray 	case B200:
88511b41d2SMark Murray 		return 200;
89511b41d2SMark Murray 	case B300:
90511b41d2SMark Murray 		return 300;
91511b41d2SMark Murray 	case B600:
92511b41d2SMark Murray 		return 600;
93511b41d2SMark Murray 	case B1200:
94511b41d2SMark Murray 		return 1200;
95511b41d2SMark Murray 	case B1800:
96511b41d2SMark Murray 		return 1800;
97511b41d2SMark Murray 	case B2400:
98511b41d2SMark Murray 		return 2400;
99511b41d2SMark Murray 	case B4800:
100511b41d2SMark Murray 		return 4800;
101511b41d2SMark Murray 	case B9600:
102511b41d2SMark Murray 		return 9600;
103511b41d2SMark Murray 
104511b41d2SMark Murray #ifdef B19200
105511b41d2SMark Murray 	case B19200:
106511b41d2SMark Murray 		return 19200;
107511b41d2SMark Murray #else /* B19200 */
108511b41d2SMark Murray #ifdef EXTA
109511b41d2SMark Murray 	case EXTA:
110511b41d2SMark Murray 		return 19200;
111511b41d2SMark Murray #endif /* EXTA */
112511b41d2SMark Murray #endif /* B19200 */
113511b41d2SMark Murray 
114511b41d2SMark Murray #ifdef B38400
115511b41d2SMark Murray 	case B38400:
116511b41d2SMark Murray 		return 38400;
117511b41d2SMark Murray #else /* B38400 */
118511b41d2SMark Murray #ifdef EXTB
119511b41d2SMark Murray 	case EXTB:
120511b41d2SMark Murray 		return 38400;
121511b41d2SMark Murray #endif /* EXTB */
122511b41d2SMark Murray #endif /* B38400 */
123511b41d2SMark Murray 
124511b41d2SMark Murray #ifdef B7200
125511b41d2SMark Murray 	case B7200:
126511b41d2SMark Murray 		return 7200;
127511b41d2SMark Murray #endif /* B7200 */
128511b41d2SMark Murray #ifdef B14400
129511b41d2SMark Murray 	case B14400:
130511b41d2SMark Murray 		return 14400;
131511b41d2SMark Murray #endif /* B14400 */
132511b41d2SMark Murray #ifdef B28800
133511b41d2SMark Murray 	case B28800:
134511b41d2SMark Murray 		return 28800;
135511b41d2SMark Murray #endif /* B28800 */
136511b41d2SMark Murray #ifdef B57600
137511b41d2SMark Murray 	case B57600:
138511b41d2SMark Murray 		return 57600;
139511b41d2SMark Murray #endif /* B57600 */
140511b41d2SMark Murray #ifdef B76800
141511b41d2SMark Murray 	case B76800:
142511b41d2SMark Murray 		return 76800;
143511b41d2SMark Murray #endif /* B76800 */
144511b41d2SMark Murray #ifdef B115200
145511b41d2SMark Murray 	case B115200:
146511b41d2SMark Murray 		return 115200;
147511b41d2SMark Murray #endif /* B115200 */
148511b41d2SMark Murray #ifdef B230400
149511b41d2SMark Murray 	case B230400:
150511b41d2SMark Murray 		return 230400;
151511b41d2SMark Murray #endif /* B230400 */
152511b41d2SMark Murray 	default:
153511b41d2SMark Murray 		return 9600;
154511b41d2SMark Murray 	}
155511b41d2SMark Murray }
156511b41d2SMark Murray 
157511b41d2SMark Murray /*
158511b41d2SMark Murray  * Converts a numeric baud rate to a POSIX speed_t.
159511b41d2SMark Murray  */
160511b41d2SMark Murray static speed_t
161511b41d2SMark Murray baud_to_speed(int baud)
162511b41d2SMark Murray {
163511b41d2SMark Murray 	switch (baud) {
164511b41d2SMark Murray 	case 0:
165511b41d2SMark Murray 		return B0;
166511b41d2SMark Murray 	case 50:
167511b41d2SMark Murray 		return B50;
168511b41d2SMark Murray 	case 75:
169511b41d2SMark Murray 		return B75;
170511b41d2SMark Murray 	case 110:
171511b41d2SMark Murray 		return B110;
172511b41d2SMark Murray 	case 134:
173511b41d2SMark Murray 		return B134;
174511b41d2SMark Murray 	case 150:
175511b41d2SMark Murray 		return B150;
176511b41d2SMark Murray 	case 200:
177511b41d2SMark Murray 		return B200;
178511b41d2SMark Murray 	case 300:
179511b41d2SMark Murray 		return B300;
180511b41d2SMark Murray 	case 600:
181511b41d2SMark Murray 		return B600;
182511b41d2SMark Murray 	case 1200:
183511b41d2SMark Murray 		return B1200;
184511b41d2SMark Murray 	case 1800:
185511b41d2SMark Murray 		return B1800;
186511b41d2SMark Murray 	case 2400:
187511b41d2SMark Murray 		return B2400;
188511b41d2SMark Murray 	case 4800:
189511b41d2SMark Murray 		return B4800;
190511b41d2SMark Murray 	case 9600:
191511b41d2SMark Murray 		return B9600;
192511b41d2SMark Murray 
193511b41d2SMark Murray #ifdef B19200
194511b41d2SMark Murray 	case 19200:
195511b41d2SMark Murray 		return B19200;
196511b41d2SMark Murray #else /* B19200 */
197511b41d2SMark Murray #ifdef EXTA
198511b41d2SMark Murray 	case 19200:
199511b41d2SMark Murray 		return EXTA;
200511b41d2SMark Murray #endif /* EXTA */
201511b41d2SMark Murray #endif /* B19200 */
202511b41d2SMark Murray 
203511b41d2SMark Murray #ifdef B38400
204511b41d2SMark Murray 	case 38400:
205511b41d2SMark Murray 		return B38400;
206511b41d2SMark Murray #else /* B38400 */
207511b41d2SMark Murray #ifdef EXTB
208511b41d2SMark Murray 	case 38400:
209511b41d2SMark Murray 		return EXTB;
210511b41d2SMark Murray #endif /* EXTB */
211511b41d2SMark Murray #endif /* B38400 */
212511b41d2SMark Murray 
213511b41d2SMark Murray #ifdef B7200
214511b41d2SMark Murray 	case 7200:
215511b41d2SMark Murray 		return B7200;
216511b41d2SMark Murray #endif /* B7200 */
217511b41d2SMark Murray #ifdef B14400
218511b41d2SMark Murray 	case 14400:
219511b41d2SMark Murray 		return B14400;
220511b41d2SMark Murray #endif /* B14400 */
221511b41d2SMark Murray #ifdef B28800
222511b41d2SMark Murray 	case 28800:
223511b41d2SMark Murray 		return B28800;
224511b41d2SMark Murray #endif /* B28800 */
225511b41d2SMark Murray #ifdef B57600
226511b41d2SMark Murray 	case 57600:
227511b41d2SMark Murray 		return B57600;
228511b41d2SMark Murray #endif /* B57600 */
229511b41d2SMark Murray #ifdef B76800
230511b41d2SMark Murray 	case 76800:
231511b41d2SMark Murray 		return B76800;
232511b41d2SMark Murray #endif /* B76800 */
233511b41d2SMark Murray #ifdef B115200
234511b41d2SMark Murray 	case 115200:
235511b41d2SMark Murray 		return B115200;
236511b41d2SMark Murray #endif /* B115200 */
237511b41d2SMark Murray #ifdef B230400
238511b41d2SMark Murray 	case 230400:
239511b41d2SMark Murray 		return B230400;
240511b41d2SMark Murray #endif /* B230400 */
241511b41d2SMark Murray 	default:
242511b41d2SMark Murray 		return B9600;
243511b41d2SMark Murray 	}
244511b41d2SMark Murray }
245511b41d2SMark Murray 
246511b41d2SMark Murray /*
247043840dfSDag-Erling Smørgrav  * Encode a special character into SSH line format.
248043840dfSDag-Erling Smørgrav  */
249043840dfSDag-Erling Smørgrav static u_int
250043840dfSDag-Erling Smørgrav special_char_encode(cc_t c)
251043840dfSDag-Erling Smørgrav {
252043840dfSDag-Erling Smørgrav #ifdef _POSIX_VDISABLE
253043840dfSDag-Erling Smørgrav 	if (c == _POSIX_VDISABLE)
254043840dfSDag-Erling Smørgrav 		return 255;
255043840dfSDag-Erling Smørgrav #endif /* _POSIX_VDISABLE */
256043840dfSDag-Erling Smørgrav 	return c;
257043840dfSDag-Erling Smørgrav }
258043840dfSDag-Erling Smørgrav 
259043840dfSDag-Erling Smørgrav /*
260043840dfSDag-Erling Smørgrav  * Decode a special character from SSH line format.
261043840dfSDag-Erling Smørgrav  */
262043840dfSDag-Erling Smørgrav static cc_t
263043840dfSDag-Erling Smørgrav special_char_decode(u_int c)
264043840dfSDag-Erling Smørgrav {
265043840dfSDag-Erling Smørgrav #ifdef _POSIX_VDISABLE
266043840dfSDag-Erling Smørgrav 	if (c == 255)
267043840dfSDag-Erling Smørgrav 		return _POSIX_VDISABLE;
268043840dfSDag-Erling Smørgrav #endif /* _POSIX_VDISABLE */
269043840dfSDag-Erling Smørgrav 	return c;
270043840dfSDag-Erling Smørgrav }
271043840dfSDag-Erling Smørgrav 
272043840dfSDag-Erling Smørgrav /*
273511b41d2SMark Murray  * Encodes terminal modes for the terminal referenced by fd
2741e8db6e2SBrian Feldman  * or tiop in a portable manner, and appends the modes to a packet
275511b41d2SMark Murray  * being constructed.
276511b41d2SMark Murray  */
277511b41d2SMark Murray void
2781e8db6e2SBrian Feldman tty_make_modes(int fd, struct termios *tiop)
279511b41d2SMark Murray {
280511b41d2SMark Murray 	struct termios tio;
281511b41d2SMark Murray 	int baud;
2821e8db6e2SBrian Feldman 	Buffer buf;
283511b41d2SMark Murray 
2841e8db6e2SBrian Feldman 	buffer_init(&buf);
2851e8db6e2SBrian Feldman 
2861e8db6e2SBrian Feldman 	if (tiop == NULL) {
287d4af9e69SDag-Erling Smørgrav 		if (fd == -1) {
288d4af9e69SDag-Erling Smørgrav 			debug("tty_make_modes: no fd or tio");
289d4af9e69SDag-Erling Smørgrav 			goto end;
290d4af9e69SDag-Erling Smørgrav 		}
2911e8db6e2SBrian Feldman 		if (tcgetattr(fd, &tio) == -1) {
292d95e11bfSDag-Erling Smørgrav 			logit("tcgetattr: %.100s", strerror(errno));
2931e8db6e2SBrian Feldman 			goto end;
2941e8db6e2SBrian Feldman 		}
2951e8db6e2SBrian Feldman 	} else
2961e8db6e2SBrian Feldman 		tio = *tiop;
2971e8db6e2SBrian Feldman 
298511b41d2SMark Murray 	/* Store input and output baud rates. */
299511b41d2SMark Murray 	baud = speed_to_baud(cfgetospeed(&tio));
300*4f52dfbbSDag-Erling Smørgrav 	buffer_put_char(&buf, TTY_OP_OSPEED);
3011e8db6e2SBrian Feldman 	buffer_put_int(&buf, baud);
302511b41d2SMark Murray 	baud = speed_to_baud(cfgetispeed(&tio));
303*4f52dfbbSDag-Erling Smørgrav 	buffer_put_char(&buf, TTY_OP_ISPEED);
3041e8db6e2SBrian Feldman 	buffer_put_int(&buf, baud);
305511b41d2SMark Murray 
306511b41d2SMark Murray 	/* Store values of mode flags. */
307511b41d2SMark Murray #define TTYCHAR(NAME, OP) \
3081e8db6e2SBrian Feldman 	buffer_put_char(&buf, OP); \
309*4f52dfbbSDag-Erling Smørgrav 	buffer_put_int(&buf, special_char_encode(tio.c_cc[NAME]));
3101e8db6e2SBrian Feldman 
311511b41d2SMark Murray #define TTYMODE(NAME, FIELD, OP) \
3121e8db6e2SBrian Feldman 	buffer_put_char(&buf, OP); \
313*4f52dfbbSDag-Erling Smørgrav 	buffer_put_int(&buf, ((tio.FIELD & NAME) != 0));
314511b41d2SMark Murray 
315511b41d2SMark Murray #include "ttymodes.h"
316511b41d2SMark Murray 
317511b41d2SMark Murray #undef TTYCHAR
318511b41d2SMark Murray #undef TTYMODE
319511b41d2SMark Murray 
3201e8db6e2SBrian Feldman end:
321511b41d2SMark Murray 	/* Mark end of mode data. */
3221e8db6e2SBrian Feldman 	buffer_put_char(&buf, TTY_OP_END);
3231e8db6e2SBrian Feldman 	packet_put_string(buffer_ptr(&buf), buffer_len(&buf));
3241e8db6e2SBrian Feldman 	buffer_free(&buf);
325511b41d2SMark Murray }
326511b41d2SMark Murray 
327511b41d2SMark Murray /*
328511b41d2SMark Murray  * Decodes terminal modes for the terminal referenced by fd in a portable
329511b41d2SMark Murray  * manner from a packet being read.
330511b41d2SMark Murray  */
331511b41d2SMark Murray void
332511b41d2SMark Murray tty_parse_modes(int fd, int *n_bytes_ptr)
333511b41d2SMark Murray {
334511b41d2SMark Murray 	struct termios tio;
335511b41d2SMark Murray 	int opcode, baud;
336511b41d2SMark Murray 	int n_bytes = 0;
337511b41d2SMark Murray 	int failure = 0;
3381e8db6e2SBrian Feldman 
3391e8db6e2SBrian Feldman 	*n_bytes_ptr = packet_get_int();
3401e8db6e2SBrian Feldman 	if (*n_bytes_ptr == 0)
3411e8db6e2SBrian Feldman 		return;
342511b41d2SMark Murray 
343511b41d2SMark Murray 	/*
344511b41d2SMark Murray 	 * Get old attributes for the terminal.  We will modify these
345511b41d2SMark Murray 	 * flags. I am hoping that if there are any machine-specific
346511b41d2SMark Murray 	 * modes, they will initially have reasonable values.
347511b41d2SMark Murray 	 */
3481e8db6e2SBrian Feldman 	if (tcgetattr(fd, &tio) == -1) {
349d95e11bfSDag-Erling Smørgrav 		logit("tcgetattr: %.100s", strerror(errno));
350511b41d2SMark Murray 		failure = -1;
3511e8db6e2SBrian Feldman 	}
352511b41d2SMark Murray 
353511b41d2SMark Murray 	for (;;) {
354511b41d2SMark Murray 		n_bytes += 1;
355511b41d2SMark Murray 		opcode = packet_get_char();
356511b41d2SMark Murray 		switch (opcode) {
357511b41d2SMark Murray 		case TTY_OP_END:
358511b41d2SMark Murray 			goto set;
359511b41d2SMark Murray 
360*4f52dfbbSDag-Erling Smørgrav 		case TTY_OP_ISPEED:
361511b41d2SMark Murray 			n_bytes += 4;
362511b41d2SMark Murray 			baud = packet_get_int();
363761efaa7SDag-Erling Smørgrav 			if (failure != -1 &&
364761efaa7SDag-Erling Smørgrav 			    cfsetispeed(&tio, baud_to_speed(baud)) == -1)
365511b41d2SMark Murray 				error("cfsetispeed failed for %d", baud);
366511b41d2SMark Murray 			break;
367511b41d2SMark Murray 
368*4f52dfbbSDag-Erling Smørgrav 		case TTY_OP_OSPEED:
369511b41d2SMark Murray 			n_bytes += 4;
370511b41d2SMark Murray 			baud = packet_get_int();
371761efaa7SDag-Erling Smørgrav 			if (failure != -1 &&
372761efaa7SDag-Erling Smørgrav 			    cfsetospeed(&tio, baud_to_speed(baud)) == -1)
373511b41d2SMark Murray 				error("cfsetospeed failed for %d", baud);
374511b41d2SMark Murray 			break;
375511b41d2SMark Murray 
376511b41d2SMark Murray #define TTYCHAR(NAME, OP) \
377511b41d2SMark Murray 	case OP: \
378*4f52dfbbSDag-Erling Smørgrav 	  n_bytes += 4; \
379*4f52dfbbSDag-Erling Smørgrav 	  tio.c_cc[NAME] = special_char_decode(packet_get_int()); \
380511b41d2SMark Murray 	  break;
381511b41d2SMark Murray #define TTYMODE(NAME, FIELD, OP) \
382511b41d2SMark Murray 	case OP: \
383*4f52dfbbSDag-Erling Smørgrav 	  n_bytes += 4; \
384*4f52dfbbSDag-Erling Smørgrav 	  if (packet_get_int()) \
385511b41d2SMark Murray 	    tio.FIELD |= NAME; \
386511b41d2SMark Murray 	  else \
387511b41d2SMark Murray 	    tio.FIELD &= ~NAME;	\
388511b41d2SMark Murray 	  break;
389511b41d2SMark Murray 
390511b41d2SMark Murray #include "ttymodes.h"
391511b41d2SMark Murray 
392511b41d2SMark Murray #undef TTYCHAR
393511b41d2SMark Murray #undef TTYMODE
394511b41d2SMark Murray 
395511b41d2SMark Murray 		default:
396511b41d2SMark Murray 			debug("Ignoring unsupported tty mode opcode %d (0x%x)",
397511b41d2SMark Murray 			    opcode, opcode);
3981e8db6e2SBrian Feldman 			/*
3991e8db6e2SBrian Feldman 			 * SSH2:
400*4f52dfbbSDag-Erling Smørgrav 			 * Opcodes 1 to 159 are defined to have a uint32
401*4f52dfbbSDag-Erling Smørgrav 			 * argument.
402*4f52dfbbSDag-Erling Smørgrav 			 * Opcodes 160 to 255 are undefined and cause parsing
403*4f52dfbbSDag-Erling Smørgrav 			 * to stop.
4041e8db6e2SBrian Feldman 			 */
4051e8db6e2SBrian Feldman 			if (opcode > 0 && opcode < 160) {
4061e8db6e2SBrian Feldman 				n_bytes += 4;
4071e8db6e2SBrian Feldman 				(void) packet_get_int();
4081e8db6e2SBrian Feldman 				break;
4091e8db6e2SBrian Feldman 			} else {
410761efaa7SDag-Erling Smørgrav 				logit("parse_tty_modes: unknown opcode %d",
411761efaa7SDag-Erling Smørgrav 				    opcode);
4121e8db6e2SBrian Feldman 				goto set;
4131e8db6e2SBrian Feldman 			}
4141e8db6e2SBrian Feldman 		}
4151e8db6e2SBrian Feldman 	}
416511b41d2SMark Murray 
417511b41d2SMark Murray set:
418511b41d2SMark Murray 	if (*n_bytes_ptr != n_bytes) {
419511b41d2SMark Murray 		*n_bytes_ptr = n_bytes;
420d95e11bfSDag-Erling Smørgrav 		logit("parse_tty_modes: n_bytes_ptr != n_bytes: %d %d",
4211e8db6e2SBrian Feldman 		    *n_bytes_ptr, n_bytes);
422511b41d2SMark Murray 		return;		/* Don't process bytes passed */
423511b41d2SMark Murray 	}
424511b41d2SMark Murray 	if (failure == -1)
4251e8db6e2SBrian Feldman 		return;		/* Packet parsed ok but tcgetattr() failed */
426511b41d2SMark Murray 
427511b41d2SMark Murray 	/* Set the new modes for the terminal. */
4281e8db6e2SBrian Feldman 	if (tcsetattr(fd, TCSANOW, &tio) == -1)
429d95e11bfSDag-Erling Smørgrav 		logit("Setting tty modes failed: %.100s", strerror(errno));
430511b41d2SMark Murray }
431