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 /* 244043840dfSDag-Erling Smørgrav * Encode a special character into SSH line format. 245043840dfSDag-Erling Smørgrav */ 246043840dfSDag-Erling Smørgrav static u_int 247043840dfSDag-Erling Smørgrav special_char_encode(cc_t c) 248043840dfSDag-Erling Smørgrav { 249043840dfSDag-Erling Smørgrav #ifdef _POSIX_VDISABLE 250043840dfSDag-Erling Smørgrav if (c == _POSIX_VDISABLE) 251043840dfSDag-Erling Smørgrav return 255; 252043840dfSDag-Erling Smørgrav #endif /* _POSIX_VDISABLE */ 253043840dfSDag-Erling Smørgrav return c; 254043840dfSDag-Erling Smørgrav } 255043840dfSDag-Erling Smørgrav 256043840dfSDag-Erling Smørgrav /* 257043840dfSDag-Erling Smørgrav * Decode a special character from SSH line format. 258043840dfSDag-Erling Smørgrav */ 259043840dfSDag-Erling Smørgrav static cc_t 260043840dfSDag-Erling Smørgrav special_char_decode(u_int c) 261043840dfSDag-Erling Smørgrav { 262043840dfSDag-Erling Smørgrav #ifdef _POSIX_VDISABLE 263043840dfSDag-Erling Smørgrav if (c == 255) 264043840dfSDag-Erling Smørgrav return _POSIX_VDISABLE; 265043840dfSDag-Erling Smørgrav #endif /* _POSIX_VDISABLE */ 266043840dfSDag-Erling Smørgrav return c; 267043840dfSDag-Erling Smørgrav } 268043840dfSDag-Erling Smørgrav 269043840dfSDag-Erling Smørgrav /* 270511b41d2SMark Murray * Encodes terminal modes for the terminal referenced by fd 2711e8db6e2SBrian Feldman * or tiop in a portable manner, and appends the modes to a packet 272511b41d2SMark Murray * being constructed. 273511b41d2SMark Murray */ 274511b41d2SMark Murray void 2751e8db6e2SBrian Feldman tty_make_modes(int fd, struct termios *tiop) 276511b41d2SMark Murray { 277511b41d2SMark Murray struct termios tio; 278511b41d2SMark Murray int baud; 2791e8db6e2SBrian Feldman Buffer buf; 2801e8db6e2SBrian Feldman int tty_op_ospeed, tty_op_ispeed; 2811e8db6e2SBrian Feldman void (*put_arg)(Buffer *, u_int); 282511b41d2SMark Murray 2831e8db6e2SBrian Feldman buffer_init(&buf); 2841e8db6e2SBrian Feldman if (compat20) { 2851e8db6e2SBrian Feldman tty_op_ospeed = TTY_OP_OSPEED_PROTO2; 2861e8db6e2SBrian Feldman tty_op_ispeed = TTY_OP_ISPEED_PROTO2; 2871e8db6e2SBrian Feldman put_arg = buffer_put_int; 2881e8db6e2SBrian Feldman } else { 2891e8db6e2SBrian Feldman tty_op_ospeed = TTY_OP_OSPEED_PROTO1; 2901e8db6e2SBrian Feldman tty_op_ispeed = TTY_OP_ISPEED_PROTO1; 2911e8db6e2SBrian Feldman put_arg = (void (*)(Buffer *, u_int)) buffer_put_char; 292511b41d2SMark Murray } 2931e8db6e2SBrian Feldman 2941e8db6e2SBrian Feldman if (tiop == NULL) { 2951e8db6e2SBrian Feldman if (tcgetattr(fd, &tio) == -1) { 296d95e11bfSDag-Erling Smørgrav logit("tcgetattr: %.100s", strerror(errno)); 2971e8db6e2SBrian Feldman goto end; 2981e8db6e2SBrian Feldman } 2991e8db6e2SBrian Feldman } else 3001e8db6e2SBrian Feldman tio = *tiop; 3011e8db6e2SBrian Feldman 302511b41d2SMark Murray /* Store input and output baud rates. */ 303511b41d2SMark Murray baud = speed_to_baud(cfgetospeed(&tio)); 304ae1f160dSDag-Erling Smørgrav debug3("tty_make_modes: ospeed %d", baud); 3051e8db6e2SBrian Feldman buffer_put_char(&buf, tty_op_ospeed); 3061e8db6e2SBrian Feldman buffer_put_int(&buf, baud); 307511b41d2SMark Murray baud = speed_to_baud(cfgetispeed(&tio)); 308ae1f160dSDag-Erling Smørgrav debug3("tty_make_modes: ispeed %d", baud); 3091e8db6e2SBrian Feldman buffer_put_char(&buf, tty_op_ispeed); 3101e8db6e2SBrian Feldman buffer_put_int(&buf, baud); 311511b41d2SMark Murray 312511b41d2SMark Murray /* Store values of mode flags. */ 313511b41d2SMark Murray #define TTYCHAR(NAME, OP) \ 314ae1f160dSDag-Erling Smørgrav debug3("tty_make_modes: %d %d", OP, tio.c_cc[NAME]); \ 3151e8db6e2SBrian Feldman buffer_put_char(&buf, OP); \ 316043840dfSDag-Erling Smørgrav put_arg(&buf, special_char_encode(tio.c_cc[NAME])); 3171e8db6e2SBrian Feldman 318511b41d2SMark Murray #define TTYMODE(NAME, FIELD, OP) \ 319ae1f160dSDag-Erling Smørgrav debug3("tty_make_modes: %d %d", OP, ((tio.FIELD & NAME) != 0)); \ 3201e8db6e2SBrian Feldman buffer_put_char(&buf, OP); \ 3211e8db6e2SBrian Feldman put_arg(&buf, ((tio.FIELD & NAME) != 0)); 322511b41d2SMark Murray 323511b41d2SMark Murray #include "ttymodes.h" 324511b41d2SMark Murray 325511b41d2SMark Murray #undef TTYCHAR 326511b41d2SMark Murray #undef TTYMODE 327511b41d2SMark Murray 3281e8db6e2SBrian Feldman end: 329511b41d2SMark Murray /* Mark end of mode data. */ 3301e8db6e2SBrian Feldman buffer_put_char(&buf, TTY_OP_END); 3311e8db6e2SBrian Feldman if (compat20) 3321e8db6e2SBrian Feldman packet_put_string(buffer_ptr(&buf), buffer_len(&buf)); 3331e8db6e2SBrian Feldman else 3341e8db6e2SBrian Feldman packet_put_raw(buffer_ptr(&buf), buffer_len(&buf)); 3351e8db6e2SBrian Feldman buffer_free(&buf); 336511b41d2SMark Murray } 337511b41d2SMark Murray 338511b41d2SMark Murray /* 339511b41d2SMark Murray * Decodes terminal modes for the terminal referenced by fd in a portable 340511b41d2SMark Murray * manner from a packet being read. 341511b41d2SMark Murray */ 342511b41d2SMark Murray void 343511b41d2SMark Murray tty_parse_modes(int fd, int *n_bytes_ptr) 344511b41d2SMark Murray { 345511b41d2SMark Murray struct termios tio; 346511b41d2SMark Murray int opcode, baud; 347511b41d2SMark Murray int n_bytes = 0; 348511b41d2SMark Murray int failure = 0; 3491e8db6e2SBrian Feldman u_int (*get_arg)(void); 3501e8db6e2SBrian Feldman int arg, arg_size; 3511e8db6e2SBrian Feldman 3521e8db6e2SBrian Feldman if (compat20) { 3531e8db6e2SBrian Feldman *n_bytes_ptr = packet_get_int(); 354ae1f160dSDag-Erling Smørgrav debug3("tty_parse_modes: SSH2 n_bytes %d", *n_bytes_ptr); 3551e8db6e2SBrian Feldman if (*n_bytes_ptr == 0) 3561e8db6e2SBrian Feldman return; 3571e8db6e2SBrian Feldman get_arg = packet_get_int; 3581e8db6e2SBrian Feldman arg_size = 4; 3591e8db6e2SBrian Feldman } else { 3601e8db6e2SBrian Feldman get_arg = packet_get_char; 3611e8db6e2SBrian Feldman arg_size = 1; 3621e8db6e2SBrian Feldman } 363511b41d2SMark Murray 364511b41d2SMark Murray /* 365511b41d2SMark Murray * Get old attributes for the terminal. We will modify these 366511b41d2SMark Murray * flags. I am hoping that if there are any machine-specific 367511b41d2SMark Murray * modes, they will initially have reasonable values. 368511b41d2SMark Murray */ 3691e8db6e2SBrian Feldman if (tcgetattr(fd, &tio) == -1) { 370d95e11bfSDag-Erling Smørgrav logit("tcgetattr: %.100s", strerror(errno)); 371511b41d2SMark Murray failure = -1; 3721e8db6e2SBrian Feldman } 373511b41d2SMark Murray 374511b41d2SMark Murray for (;;) { 375511b41d2SMark Murray n_bytes += 1; 376511b41d2SMark Murray opcode = packet_get_char(); 377511b41d2SMark Murray switch (opcode) { 378511b41d2SMark Murray case TTY_OP_END: 379511b41d2SMark Murray goto set; 380511b41d2SMark Murray 3811e8db6e2SBrian Feldman /* XXX: future conflict possible */ 3821e8db6e2SBrian Feldman case TTY_OP_ISPEED_PROTO1: 3831e8db6e2SBrian Feldman case TTY_OP_ISPEED_PROTO2: 384511b41d2SMark Murray n_bytes += 4; 385511b41d2SMark Murray baud = packet_get_int(); 386ae1f160dSDag-Erling Smørgrav debug3("tty_parse_modes: ispeed %d", baud); 3871e8db6e2SBrian Feldman if (failure != -1 && cfsetispeed(&tio, baud_to_speed(baud)) == -1) 388511b41d2SMark Murray error("cfsetispeed failed for %d", baud); 389511b41d2SMark Murray break; 390511b41d2SMark Murray 3911e8db6e2SBrian Feldman /* XXX: future conflict possible */ 3921e8db6e2SBrian Feldman case TTY_OP_OSPEED_PROTO1: 3931e8db6e2SBrian Feldman case TTY_OP_OSPEED_PROTO2: 394511b41d2SMark Murray n_bytes += 4; 395511b41d2SMark Murray baud = packet_get_int(); 396ae1f160dSDag-Erling Smørgrav debug3("tty_parse_modes: ospeed %d", baud); 3971e8db6e2SBrian Feldman if (failure != -1 && cfsetospeed(&tio, baud_to_speed(baud)) == -1) 398511b41d2SMark Murray error("cfsetospeed failed for %d", baud); 399511b41d2SMark Murray break; 400511b41d2SMark Murray 401511b41d2SMark Murray #define TTYCHAR(NAME, OP) \ 402511b41d2SMark Murray case OP: \ 4031e8db6e2SBrian Feldman n_bytes += arg_size; \ 404043840dfSDag-Erling Smørgrav tio.c_cc[NAME] = special_char_decode(get_arg()); \ 405ae1f160dSDag-Erling Smørgrav debug3("tty_parse_modes: %d %d", OP, tio.c_cc[NAME]); \ 406511b41d2SMark Murray break; 407511b41d2SMark Murray #define TTYMODE(NAME, FIELD, OP) \ 408511b41d2SMark Murray case OP: \ 4091e8db6e2SBrian Feldman n_bytes += arg_size; \ 4101e8db6e2SBrian Feldman if ((arg = get_arg())) \ 411511b41d2SMark Murray tio.FIELD |= NAME; \ 412511b41d2SMark Murray else \ 413511b41d2SMark Murray tio.FIELD &= ~NAME; \ 414ae1f160dSDag-Erling Smørgrav debug3("tty_parse_modes: %d %d", OP, arg); \ 415511b41d2SMark Murray break; 416511b41d2SMark Murray 417511b41d2SMark Murray #include "ttymodes.h" 418511b41d2SMark Murray 419511b41d2SMark Murray #undef TTYCHAR 420511b41d2SMark Murray #undef TTYMODE 421511b41d2SMark Murray 422511b41d2SMark Murray default: 423511b41d2SMark Murray debug("Ignoring unsupported tty mode opcode %d (0x%x)", 424511b41d2SMark Murray opcode, opcode); 4251e8db6e2SBrian Feldman if (!compat20) { 426511b41d2SMark Murray /* 4271e8db6e2SBrian Feldman * SSH1: 4281e8db6e2SBrian Feldman * Opcodes 1 to 127 are defined to have 429511b41d2SMark Murray * a one-byte argument. 430511b41d2SMark Murray * Opcodes 128 to 159 are defined to have 431511b41d2SMark Murray * an integer argument. 432511b41d2SMark Murray */ 4331e8db6e2SBrian Feldman if (opcode > 0 && opcode < 128) { 4341e8db6e2SBrian Feldman n_bytes += 1; 4351e8db6e2SBrian Feldman (void) packet_get_char(); 4361e8db6e2SBrian Feldman break; 4371e8db6e2SBrian Feldman } else if (opcode >= 128 && opcode < 160) { 438511b41d2SMark Murray n_bytes += 4; 439511b41d2SMark Murray (void) packet_get_int(); 440511b41d2SMark Murray break; 4411e8db6e2SBrian Feldman } else { 442511b41d2SMark Murray /* 443511b41d2SMark Murray * It is a truly undefined opcode (160 to 255). 444511b41d2SMark Murray * We have no idea about its arguments. So we 445511b41d2SMark Murray * must stop parsing. Note that some data may be 446511b41d2SMark Murray * left in the packet; hopefully there is nothing 447511b41d2SMark Murray * more coming after the mode data. 448511b41d2SMark Murray */ 449d95e11bfSDag-Erling Smørgrav logit("parse_tty_modes: unknown opcode %d", opcode); 450511b41d2SMark Murray goto set; 451511b41d2SMark Murray } 4521e8db6e2SBrian Feldman } else { 4531e8db6e2SBrian Feldman /* 4541e8db6e2SBrian Feldman * SSH2: 4551e8db6e2SBrian Feldman * Opcodes 1 to 159 are defined to have 4561e8db6e2SBrian Feldman * a uint32 argument. 4571e8db6e2SBrian Feldman * Opcodes 160 to 255 are undefined and 4581e8db6e2SBrian Feldman * cause parsing to stop. 4591e8db6e2SBrian Feldman */ 4601e8db6e2SBrian Feldman if (opcode > 0 && opcode < 160) { 4611e8db6e2SBrian Feldman n_bytes += 4; 4621e8db6e2SBrian Feldman (void) packet_get_int(); 4631e8db6e2SBrian Feldman break; 4641e8db6e2SBrian Feldman } else { 465d95e11bfSDag-Erling Smørgrav logit("parse_tty_modes: unknown opcode %d", opcode); 4661e8db6e2SBrian Feldman goto set; 4671e8db6e2SBrian Feldman } 4681e8db6e2SBrian Feldman } 4691e8db6e2SBrian Feldman } 470511b41d2SMark Murray } 471511b41d2SMark Murray 472511b41d2SMark Murray set: 473511b41d2SMark Murray if (*n_bytes_ptr != n_bytes) { 474511b41d2SMark Murray *n_bytes_ptr = n_bytes; 475d95e11bfSDag-Erling Smørgrav logit("parse_tty_modes: n_bytes_ptr != n_bytes: %d %d", 4761e8db6e2SBrian Feldman *n_bytes_ptr, n_bytes); 477511b41d2SMark Murray return; /* Don't process bytes passed */ 478511b41d2SMark Murray } 479511b41d2SMark Murray if (failure == -1) 4801e8db6e2SBrian Feldman return; /* Packet parsed ok but tcgetattr() failed */ 481511b41d2SMark Murray 482511b41d2SMark Murray /* Set the new modes for the terminal. */ 4831e8db6e2SBrian Feldman if (tcsetattr(fd, TCSANOW, &tio) == -1) 484d95e11bfSDag-Erling Smørgrav logit("Setting tty modes failed: %.100s", strerror(errno)); 485511b41d2SMark Murray } 486