10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * Author: Tatu Ylonen <ylo@cs.hut.fi>
30Sstevel@tonic-gate * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
40Sstevel@tonic-gate * All rights reserved
50Sstevel@tonic-gate *
60Sstevel@tonic-gate * As far as I am concerned, the code I have written for this software
70Sstevel@tonic-gate * can be used freely for any purpose. Any derived versions of this
80Sstevel@tonic-gate * software must be clearly marked as such, and if the derived work is
90Sstevel@tonic-gate * incompatible with the protocol description in the RFC file, it must be
100Sstevel@tonic-gate * called by a name other than "ssh" or "Secure Shell".
110Sstevel@tonic-gate */
120Sstevel@tonic-gate
130Sstevel@tonic-gate /*
140Sstevel@tonic-gate * SSH2 tty modes support by Kevin Steves.
150Sstevel@tonic-gate * Copyright (c) 2001 Kevin Steves. All rights reserved.
160Sstevel@tonic-gate *
170Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without
180Sstevel@tonic-gate * modification, are permitted provided that the following conditions
190Sstevel@tonic-gate * are met:
200Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright
210Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer.
220Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright
230Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the
240Sstevel@tonic-gate * documentation and/or other materials provided with the distribution.
250Sstevel@tonic-gate *
260Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
270Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
280Sstevel@tonic-gate * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
290Sstevel@tonic-gate * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
300Sstevel@tonic-gate * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
310Sstevel@tonic-gate * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
320Sstevel@tonic-gate * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
330Sstevel@tonic-gate * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
340Sstevel@tonic-gate * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
350Sstevel@tonic-gate * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
360Sstevel@tonic-gate */
37*9354STim.Marsland@Sun.COM
380Sstevel@tonic-gate /*
39*9354STim.Marsland@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
400Sstevel@tonic-gate * Use is subject to license terms.
410Sstevel@tonic-gate */
420Sstevel@tonic-gate
430Sstevel@tonic-gate /*
440Sstevel@tonic-gate * Encoding and decoding of terminal modes in a portable way.
450Sstevel@tonic-gate * Much of the format is defined in ttymodes.h; it is included multiple times
460Sstevel@tonic-gate * into this file with the appropriate macro definitions to generate the
470Sstevel@tonic-gate * suitable code.
480Sstevel@tonic-gate */
490Sstevel@tonic-gate
500Sstevel@tonic-gate #include "includes.h"
510Sstevel@tonic-gate RCSID("$OpenBSD: ttymodes.c,v 1.18 2002/06/19 00:27:55 deraadt Exp $");
520Sstevel@tonic-gate
530Sstevel@tonic-gate #include "packet.h"
540Sstevel@tonic-gate #include "log.h"
550Sstevel@tonic-gate #include "ssh1.h"
560Sstevel@tonic-gate #include "compat.h"
570Sstevel@tonic-gate #include "buffer.h"
580Sstevel@tonic-gate #include "bufaux.h"
590Sstevel@tonic-gate
600Sstevel@tonic-gate #define TTY_OP_END 0
610Sstevel@tonic-gate /*
620Sstevel@tonic-gate * uint32 (u_int) follows speed in SSH1 and SSH2
630Sstevel@tonic-gate */
640Sstevel@tonic-gate #define TTY_OP_ISPEED_PROTO1 192
650Sstevel@tonic-gate #define TTY_OP_OSPEED_PROTO1 193
660Sstevel@tonic-gate #define TTY_OP_ISPEED_PROTO2 128
670Sstevel@tonic-gate #define TTY_OP_OSPEED_PROTO2 129
680Sstevel@tonic-gate
690Sstevel@tonic-gate /*
700Sstevel@tonic-gate * Converts POSIX speed_t to a baud rate. The values of the
710Sstevel@tonic-gate * constants for speed_t are not themselves portable.
720Sstevel@tonic-gate */
730Sstevel@tonic-gate static int
speed_to_baud(speed_t speed)740Sstevel@tonic-gate speed_to_baud(speed_t speed)
750Sstevel@tonic-gate {
760Sstevel@tonic-gate switch (speed) {
770Sstevel@tonic-gate case B0:
780Sstevel@tonic-gate return 0;
790Sstevel@tonic-gate case B50:
800Sstevel@tonic-gate return 50;
810Sstevel@tonic-gate case B75:
820Sstevel@tonic-gate return 75;
830Sstevel@tonic-gate case B110:
840Sstevel@tonic-gate return 110;
850Sstevel@tonic-gate case B134:
860Sstevel@tonic-gate return 134;
870Sstevel@tonic-gate case B150:
880Sstevel@tonic-gate return 150;
890Sstevel@tonic-gate case B200:
900Sstevel@tonic-gate return 200;
910Sstevel@tonic-gate case B300:
920Sstevel@tonic-gate return 300;
930Sstevel@tonic-gate case B600:
940Sstevel@tonic-gate return 600;
950Sstevel@tonic-gate case B1200:
960Sstevel@tonic-gate return 1200;
970Sstevel@tonic-gate case B1800:
980Sstevel@tonic-gate return 1800;
990Sstevel@tonic-gate case B2400:
1000Sstevel@tonic-gate return 2400;
1010Sstevel@tonic-gate case B4800:
1020Sstevel@tonic-gate return 4800;
1030Sstevel@tonic-gate case B9600:
1040Sstevel@tonic-gate return 9600;
1050Sstevel@tonic-gate
1060Sstevel@tonic-gate #ifdef B19200
1070Sstevel@tonic-gate case B19200:
1080Sstevel@tonic-gate return 19200;
1090Sstevel@tonic-gate #else /* B19200 */
1100Sstevel@tonic-gate #ifdef EXTA
1110Sstevel@tonic-gate case EXTA:
1120Sstevel@tonic-gate return 19200;
1130Sstevel@tonic-gate #endif /* EXTA */
1140Sstevel@tonic-gate #endif /* B19200 */
1150Sstevel@tonic-gate
1160Sstevel@tonic-gate #ifdef B38400
1170Sstevel@tonic-gate case B38400:
1180Sstevel@tonic-gate return 38400;
1190Sstevel@tonic-gate #else /* B38400 */
1200Sstevel@tonic-gate #ifdef EXTB
1210Sstevel@tonic-gate case EXTB:
1220Sstevel@tonic-gate return 38400;
1230Sstevel@tonic-gate #endif /* EXTB */
1240Sstevel@tonic-gate #endif /* B38400 */
1250Sstevel@tonic-gate
1260Sstevel@tonic-gate #ifdef B7200
1270Sstevel@tonic-gate case B7200:
1280Sstevel@tonic-gate return 7200;
1290Sstevel@tonic-gate #endif /* B7200 */
1300Sstevel@tonic-gate #ifdef B14400
1310Sstevel@tonic-gate case B14400:
1320Sstevel@tonic-gate return 14400;
1330Sstevel@tonic-gate #endif /* B14400 */
1340Sstevel@tonic-gate #ifdef B28800
1350Sstevel@tonic-gate case B28800:
1360Sstevel@tonic-gate return 28800;
1370Sstevel@tonic-gate #endif /* B28800 */
1380Sstevel@tonic-gate #ifdef B57600
1390Sstevel@tonic-gate case B57600:
1400Sstevel@tonic-gate return 57600;
1410Sstevel@tonic-gate #endif /* B57600 */
1420Sstevel@tonic-gate #ifdef B76800
1430Sstevel@tonic-gate case B76800:
1440Sstevel@tonic-gate return 76800;
1450Sstevel@tonic-gate #endif /* B76800 */
1460Sstevel@tonic-gate #ifdef B115200
1470Sstevel@tonic-gate case B115200:
1480Sstevel@tonic-gate return 115200;
1490Sstevel@tonic-gate #endif /* B115200 */
1500Sstevel@tonic-gate #ifdef B230400
1510Sstevel@tonic-gate case B230400:
1520Sstevel@tonic-gate return 230400;
1530Sstevel@tonic-gate #endif /* B230400 */
154*9354STim.Marsland@Sun.COM #ifdef B460800
155*9354STim.Marsland@Sun.COM case B460800:
156*9354STim.Marsland@Sun.COM return 460800;
157*9354STim.Marsland@Sun.COM #endif /* B460800 */
158*9354STim.Marsland@Sun.COM #ifdef B921600
159*9354STim.Marsland@Sun.COM case B921600:
160*9354STim.Marsland@Sun.COM return 921600;
161*9354STim.Marsland@Sun.COM #endif /* B921600 */
1620Sstevel@tonic-gate default:
1630Sstevel@tonic-gate return 9600;
1640Sstevel@tonic-gate }
1650Sstevel@tonic-gate }
1660Sstevel@tonic-gate
1670Sstevel@tonic-gate /*
1680Sstevel@tonic-gate * Converts a numeric baud rate to a POSIX speed_t.
1690Sstevel@tonic-gate */
1700Sstevel@tonic-gate static speed_t
baud_to_speed(int baud)1710Sstevel@tonic-gate baud_to_speed(int baud)
1720Sstevel@tonic-gate {
1730Sstevel@tonic-gate switch (baud) {
1740Sstevel@tonic-gate case 0:
1750Sstevel@tonic-gate return B0;
1760Sstevel@tonic-gate case 50:
1770Sstevel@tonic-gate return B50;
1780Sstevel@tonic-gate case 75:
1790Sstevel@tonic-gate return B75;
1800Sstevel@tonic-gate case 110:
1810Sstevel@tonic-gate return B110;
1820Sstevel@tonic-gate case 134:
1830Sstevel@tonic-gate return B134;
1840Sstevel@tonic-gate case 150:
1850Sstevel@tonic-gate return B150;
1860Sstevel@tonic-gate case 200:
1870Sstevel@tonic-gate return B200;
1880Sstevel@tonic-gate case 300:
1890Sstevel@tonic-gate return B300;
1900Sstevel@tonic-gate case 600:
1910Sstevel@tonic-gate return B600;
1920Sstevel@tonic-gate case 1200:
1930Sstevel@tonic-gate return B1200;
1940Sstevel@tonic-gate case 1800:
1950Sstevel@tonic-gate return B1800;
1960Sstevel@tonic-gate case 2400:
1970Sstevel@tonic-gate return B2400;
1980Sstevel@tonic-gate case 4800:
1990Sstevel@tonic-gate return B4800;
2000Sstevel@tonic-gate case 9600:
2010Sstevel@tonic-gate return B9600;
2020Sstevel@tonic-gate
2030Sstevel@tonic-gate #ifdef B19200
2040Sstevel@tonic-gate case 19200:
2050Sstevel@tonic-gate return B19200;
2060Sstevel@tonic-gate #else /* B19200 */
2070Sstevel@tonic-gate #ifdef EXTA
2080Sstevel@tonic-gate case 19200:
2090Sstevel@tonic-gate return EXTA;
2100Sstevel@tonic-gate #endif /* EXTA */
2110Sstevel@tonic-gate #endif /* B19200 */
2120Sstevel@tonic-gate
2130Sstevel@tonic-gate #ifdef B38400
2140Sstevel@tonic-gate case 38400:
2150Sstevel@tonic-gate return B38400;
2160Sstevel@tonic-gate #else /* B38400 */
2170Sstevel@tonic-gate #ifdef EXTB
2180Sstevel@tonic-gate case 38400:
2190Sstevel@tonic-gate return EXTB;
2200Sstevel@tonic-gate #endif /* EXTB */
2210Sstevel@tonic-gate #endif /* B38400 */
2220Sstevel@tonic-gate
2230Sstevel@tonic-gate #ifdef B7200
2240Sstevel@tonic-gate case 7200:
2250Sstevel@tonic-gate return B7200;
2260Sstevel@tonic-gate #endif /* B7200 */
2270Sstevel@tonic-gate #ifdef B14400
2280Sstevel@tonic-gate case 14400:
2290Sstevel@tonic-gate return B14400;
2300Sstevel@tonic-gate #endif /* B14400 */
2310Sstevel@tonic-gate #ifdef B28800
2320Sstevel@tonic-gate case 28800:
2330Sstevel@tonic-gate return B28800;
2340Sstevel@tonic-gate #endif /* B28800 */
2350Sstevel@tonic-gate #ifdef B57600
2360Sstevel@tonic-gate case 57600:
2370Sstevel@tonic-gate return B57600;
2380Sstevel@tonic-gate #endif /* B57600 */
2390Sstevel@tonic-gate #ifdef B76800
2400Sstevel@tonic-gate case 76800:
2410Sstevel@tonic-gate return B76800;
2420Sstevel@tonic-gate #endif /* B76800 */
2430Sstevel@tonic-gate #ifdef B115200
2440Sstevel@tonic-gate case 115200:
2450Sstevel@tonic-gate return B115200;
2460Sstevel@tonic-gate #endif /* B115200 */
2470Sstevel@tonic-gate #ifdef B230400
2480Sstevel@tonic-gate case 230400:
2490Sstevel@tonic-gate return B230400;
2500Sstevel@tonic-gate #endif /* B230400 */
251*9354STim.Marsland@Sun.COM #ifdef B460800
252*9354STim.Marsland@Sun.COM case 460800:
253*9354STim.Marsland@Sun.COM return B460800;
254*9354STim.Marsland@Sun.COM #endif /* B460800 */
255*9354STim.Marsland@Sun.COM #ifdef B921600
256*9354STim.Marsland@Sun.COM case 921600:
257*9354STim.Marsland@Sun.COM return B921600;
258*9354STim.Marsland@Sun.COM #endif /* B921600 */
2590Sstevel@tonic-gate default:
2600Sstevel@tonic-gate return B9600;
2610Sstevel@tonic-gate }
2620Sstevel@tonic-gate }
2630Sstevel@tonic-gate
2640Sstevel@tonic-gate /*
2650Sstevel@tonic-gate * Encodes terminal modes for the terminal referenced by fd
2660Sstevel@tonic-gate * or tiop in a portable manner, and appends the modes to a packet
2670Sstevel@tonic-gate * being constructed.
2680Sstevel@tonic-gate */
2690Sstevel@tonic-gate void
tty_make_modes(int fd,struct termios * tiop)2700Sstevel@tonic-gate tty_make_modes(int fd, struct termios *tiop)
2710Sstevel@tonic-gate {
2720Sstevel@tonic-gate struct termios tio;
2730Sstevel@tonic-gate int baud;
2740Sstevel@tonic-gate Buffer buf;
2750Sstevel@tonic-gate int tty_op_ospeed, tty_op_ispeed;
2760Sstevel@tonic-gate void (*put_arg)(Buffer *, u_int);
2770Sstevel@tonic-gate
2780Sstevel@tonic-gate buffer_init(&buf);
2790Sstevel@tonic-gate if (compat20) {
2800Sstevel@tonic-gate tty_op_ospeed = TTY_OP_OSPEED_PROTO2;
2810Sstevel@tonic-gate tty_op_ispeed = TTY_OP_ISPEED_PROTO2;
2820Sstevel@tonic-gate put_arg = buffer_put_int;
2830Sstevel@tonic-gate } else {
2840Sstevel@tonic-gate tty_op_ospeed = TTY_OP_OSPEED_PROTO1;
2850Sstevel@tonic-gate tty_op_ispeed = TTY_OP_ISPEED_PROTO1;
2860Sstevel@tonic-gate put_arg = (void (*)(Buffer *, u_int)) buffer_put_char;
2870Sstevel@tonic-gate }
2880Sstevel@tonic-gate
2890Sstevel@tonic-gate if (tiop == NULL) {
2900Sstevel@tonic-gate if (tcgetattr(fd, &tio) == -1) {
2910Sstevel@tonic-gate log("tcgetattr: %.100s", strerror(errno));
2920Sstevel@tonic-gate goto end;
2930Sstevel@tonic-gate }
2940Sstevel@tonic-gate } else
2950Sstevel@tonic-gate tio = *tiop;
2960Sstevel@tonic-gate
2970Sstevel@tonic-gate /* Store input and output baud rates. */
2980Sstevel@tonic-gate baud = speed_to_baud(cfgetospeed(&tio));
2990Sstevel@tonic-gate debug3("tty_make_modes: ospeed %d", baud);
3000Sstevel@tonic-gate buffer_put_char(&buf, tty_op_ospeed);
3010Sstevel@tonic-gate buffer_put_int(&buf, baud);
3020Sstevel@tonic-gate baud = speed_to_baud(cfgetispeed(&tio));
3030Sstevel@tonic-gate debug3("tty_make_modes: ispeed %d", baud);
3040Sstevel@tonic-gate buffer_put_char(&buf, tty_op_ispeed);
3050Sstevel@tonic-gate buffer_put_int(&buf, baud);
3060Sstevel@tonic-gate
3070Sstevel@tonic-gate /* Store values of mode flags. */
3080Sstevel@tonic-gate #define TTYCHAR(NAME, OP) \
3090Sstevel@tonic-gate debug3("tty_make_modes: %d %d", OP, tio.c_cc[NAME]); \
3100Sstevel@tonic-gate buffer_put_char(&buf, OP); \
3110Sstevel@tonic-gate put_arg(&buf, tio.c_cc[NAME]);
3120Sstevel@tonic-gate
3130Sstevel@tonic-gate #define TTYMODE(NAME, FIELD, OP) \
3140Sstevel@tonic-gate debug3("tty_make_modes: %d %d", OP, ((tio.FIELD & NAME) != 0)); \
3150Sstevel@tonic-gate buffer_put_char(&buf, OP); \
3160Sstevel@tonic-gate put_arg(&buf, ((tio.FIELD & NAME) != 0));
3170Sstevel@tonic-gate
3180Sstevel@tonic-gate #include "ttymodes.h"
3190Sstevel@tonic-gate
3200Sstevel@tonic-gate #undef TTYCHAR
3210Sstevel@tonic-gate #undef TTYMODE
3220Sstevel@tonic-gate
3230Sstevel@tonic-gate end:
3240Sstevel@tonic-gate /* Mark end of mode data. */
3250Sstevel@tonic-gate buffer_put_char(&buf, TTY_OP_END);
3260Sstevel@tonic-gate if (compat20)
3270Sstevel@tonic-gate packet_put_string(buffer_ptr(&buf), buffer_len(&buf));
3280Sstevel@tonic-gate else
3290Sstevel@tonic-gate packet_put_raw(buffer_ptr(&buf), buffer_len(&buf));
3300Sstevel@tonic-gate buffer_free(&buf);
3310Sstevel@tonic-gate }
3320Sstevel@tonic-gate
3330Sstevel@tonic-gate /*
3340Sstevel@tonic-gate * Decodes terminal modes for the terminal referenced by fd in a portable
3350Sstevel@tonic-gate * manner from a packet being read.
3360Sstevel@tonic-gate */
3370Sstevel@tonic-gate void
tty_parse_modes(int fd,int * n_bytes_ptr)3380Sstevel@tonic-gate tty_parse_modes(int fd, int *n_bytes_ptr)
3390Sstevel@tonic-gate {
3400Sstevel@tonic-gate struct termios tio;
3410Sstevel@tonic-gate int opcode, baud;
3420Sstevel@tonic-gate int n_bytes = 0;
3430Sstevel@tonic-gate int failure = 0;
3440Sstevel@tonic-gate u_int (*get_arg)(void);
3450Sstevel@tonic-gate int arg, arg_size;
3460Sstevel@tonic-gate
3470Sstevel@tonic-gate if (compat20) {
3480Sstevel@tonic-gate *n_bytes_ptr = packet_get_int();
3490Sstevel@tonic-gate debug3("tty_parse_modes: SSH2 n_bytes %d", *n_bytes_ptr);
3500Sstevel@tonic-gate if (*n_bytes_ptr == 0)
3510Sstevel@tonic-gate return;
3520Sstevel@tonic-gate get_arg = packet_get_int;
3530Sstevel@tonic-gate arg_size = 4;
3540Sstevel@tonic-gate } else {
3550Sstevel@tonic-gate get_arg = packet_get_char;
3560Sstevel@tonic-gate arg_size = 1;
3570Sstevel@tonic-gate }
3580Sstevel@tonic-gate
3590Sstevel@tonic-gate /*
3600Sstevel@tonic-gate * Get old attributes for the terminal. We will modify these
3610Sstevel@tonic-gate * flags. I am hoping that if there are any machine-specific
3620Sstevel@tonic-gate * modes, they will initially have reasonable values.
3630Sstevel@tonic-gate */
3640Sstevel@tonic-gate if (tcgetattr(fd, &tio) == -1) {
3650Sstevel@tonic-gate log("tcgetattr: %.100s", strerror(errno));
3660Sstevel@tonic-gate failure = -1;
3670Sstevel@tonic-gate }
3680Sstevel@tonic-gate
3690Sstevel@tonic-gate for (;;) {
3700Sstevel@tonic-gate n_bytes += 1;
3710Sstevel@tonic-gate opcode = packet_get_char();
3720Sstevel@tonic-gate switch (opcode) {
3730Sstevel@tonic-gate case TTY_OP_END:
3740Sstevel@tonic-gate goto set;
3750Sstevel@tonic-gate
3760Sstevel@tonic-gate /* XXX: future conflict possible */
3770Sstevel@tonic-gate case TTY_OP_ISPEED_PROTO1:
3780Sstevel@tonic-gate case TTY_OP_ISPEED_PROTO2:
3790Sstevel@tonic-gate n_bytes += 4;
3800Sstevel@tonic-gate baud = packet_get_int();
3810Sstevel@tonic-gate debug3("tty_parse_modes: ispeed %d", baud);
3820Sstevel@tonic-gate if (failure != -1 && cfsetispeed(&tio, baud_to_speed(baud)) == -1)
3830Sstevel@tonic-gate error("cfsetispeed failed for %d", baud);
3840Sstevel@tonic-gate break;
3850Sstevel@tonic-gate
3860Sstevel@tonic-gate /* XXX: future conflict possible */
3870Sstevel@tonic-gate case TTY_OP_OSPEED_PROTO1:
3880Sstevel@tonic-gate case TTY_OP_OSPEED_PROTO2:
3890Sstevel@tonic-gate n_bytes += 4;
3900Sstevel@tonic-gate baud = packet_get_int();
3910Sstevel@tonic-gate debug3("tty_parse_modes: ospeed %d", baud);
3920Sstevel@tonic-gate if (failure != -1 && cfsetospeed(&tio, baud_to_speed(baud)) == -1)
3930Sstevel@tonic-gate error("cfsetospeed failed for %d", baud);
3940Sstevel@tonic-gate break;
3950Sstevel@tonic-gate
3960Sstevel@tonic-gate #define TTYCHAR(NAME, OP) \
3970Sstevel@tonic-gate case OP: \
3980Sstevel@tonic-gate n_bytes += arg_size; \
3990Sstevel@tonic-gate tio.c_cc[NAME] = get_arg(); \
4000Sstevel@tonic-gate debug3("tty_parse_modes: %d %d", OP, tio.c_cc[NAME]); \
4010Sstevel@tonic-gate break;
4020Sstevel@tonic-gate #define TTYMODE(NAME, FIELD, OP) \
4030Sstevel@tonic-gate case OP: \
4040Sstevel@tonic-gate n_bytes += arg_size; \
4050Sstevel@tonic-gate if ((arg = get_arg())) \
4060Sstevel@tonic-gate tio.FIELD |= NAME; \
4070Sstevel@tonic-gate else \
4080Sstevel@tonic-gate tio.FIELD &= ~NAME; \
4090Sstevel@tonic-gate debug3("tty_parse_modes: %d %d", OP, arg); \
4100Sstevel@tonic-gate break;
4110Sstevel@tonic-gate
4120Sstevel@tonic-gate #include "ttymodes.h"
4130Sstevel@tonic-gate
4140Sstevel@tonic-gate #undef TTYCHAR
4150Sstevel@tonic-gate #undef TTYMODE
4160Sstevel@tonic-gate
4170Sstevel@tonic-gate default:
4180Sstevel@tonic-gate debug("Ignoring unsupported tty mode opcode %d (0x%x)",
4190Sstevel@tonic-gate opcode, opcode);
4200Sstevel@tonic-gate if (!compat20) {
4210Sstevel@tonic-gate /*
4220Sstevel@tonic-gate * SSH1:
4230Sstevel@tonic-gate * Opcodes 1 to 127 are defined to have
4240Sstevel@tonic-gate * a one-byte argument.
4250Sstevel@tonic-gate * Opcodes 128 to 159 are defined to have
4260Sstevel@tonic-gate * an integer argument.
4270Sstevel@tonic-gate */
4280Sstevel@tonic-gate if (opcode > 0 && opcode < 128) {
4290Sstevel@tonic-gate n_bytes += 1;
4300Sstevel@tonic-gate (void) packet_get_char();
4310Sstevel@tonic-gate break;
4320Sstevel@tonic-gate } else if (opcode >= 128 && opcode < 160) {
4330Sstevel@tonic-gate n_bytes += 4;
4340Sstevel@tonic-gate (void) packet_get_int();
4350Sstevel@tonic-gate break;
4360Sstevel@tonic-gate } else {
4370Sstevel@tonic-gate /*
4380Sstevel@tonic-gate * It is a truly undefined opcode (160 to 255).
4390Sstevel@tonic-gate * We have no idea about its arguments. So we
4400Sstevel@tonic-gate * must stop parsing. Note that some data may be
4410Sstevel@tonic-gate * left in the packet; hopefully there is nothing
4420Sstevel@tonic-gate * more coming after the mode data.
4430Sstevel@tonic-gate */
4440Sstevel@tonic-gate log("parse_tty_modes: unknown opcode %d", opcode);
4450Sstevel@tonic-gate goto set;
4460Sstevel@tonic-gate }
4470Sstevel@tonic-gate } else {
4480Sstevel@tonic-gate /*
4490Sstevel@tonic-gate * SSH2:
4500Sstevel@tonic-gate * Opcodes 1 to 159 are defined to have
4510Sstevel@tonic-gate * a uint32 argument.
4520Sstevel@tonic-gate * Opcodes 160 to 255 are undefined and
4530Sstevel@tonic-gate * cause parsing to stop.
4540Sstevel@tonic-gate */
4550Sstevel@tonic-gate if (opcode > 0 && opcode < 160) {
4560Sstevel@tonic-gate n_bytes += 4;
4570Sstevel@tonic-gate (void) packet_get_int();
4580Sstevel@tonic-gate break;
4590Sstevel@tonic-gate } else {
4600Sstevel@tonic-gate log("parse_tty_modes: unknown opcode %d", opcode);
4610Sstevel@tonic-gate goto set;
4620Sstevel@tonic-gate }
4630Sstevel@tonic-gate }
4640Sstevel@tonic-gate }
4650Sstevel@tonic-gate }
4660Sstevel@tonic-gate
4670Sstevel@tonic-gate set:
4680Sstevel@tonic-gate if (*n_bytes_ptr != n_bytes) {
4690Sstevel@tonic-gate *n_bytes_ptr = n_bytes;
4700Sstevel@tonic-gate log("parse_tty_modes: n_bytes_ptr != n_bytes: %d %d",
4710Sstevel@tonic-gate *n_bytes_ptr, n_bytes);
4720Sstevel@tonic-gate return; /* Don't process bytes passed */
4730Sstevel@tonic-gate }
4740Sstevel@tonic-gate if (failure == -1)
4750Sstevel@tonic-gate return; /* Packet parsed ok but tcgetattr() failed */
4760Sstevel@tonic-gate
4770Sstevel@tonic-gate /* Set the new modes for the terminal. */
4780Sstevel@tonic-gate if (tcsetattr(fd, TCSANOW, &tio) == -1)
4790Sstevel@tonic-gate log("Setting tty modes failed: %.100s", strerror(errno));
4800Sstevel@tonic-gate }
481