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 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 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 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 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