1d4af9e69SDag-Erling Smørgrav /* $OpenBSD: ttymodes.c,v 1.28 2008/07/07 00:31:41 stevesk 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 "ssh1.h" 581e8db6e2SBrian Feldman #include "compat.h" 591e8db6e2SBrian Feldman #include "buffer.h" 60511b41d2SMark Murray 61511b41d2SMark Murray #define TTY_OP_END 0 621e8db6e2SBrian Feldman /* 631e8db6e2SBrian Feldman * uint32 (u_int) follows speed in SSH1 and SSH2 641e8db6e2SBrian Feldman */ 651e8db6e2SBrian Feldman #define TTY_OP_ISPEED_PROTO1 192 661e8db6e2SBrian Feldman #define TTY_OP_OSPEED_PROTO1 193 671e8db6e2SBrian Feldman #define TTY_OP_ISPEED_PROTO2 128 681e8db6e2SBrian Feldman #define TTY_OP_OSPEED_PROTO2 129 69511b41d2SMark Murray 70511b41d2SMark Murray /* 71511b41d2SMark Murray * Converts POSIX speed_t to a baud rate. The values of the 72511b41d2SMark Murray * constants for speed_t are not themselves portable. 73511b41d2SMark Murray */ 74511b41d2SMark Murray static int 75511b41d2SMark Murray speed_to_baud(speed_t speed) 76511b41d2SMark Murray { 77511b41d2SMark Murray switch (speed) { 78511b41d2SMark Murray case B0: 79511b41d2SMark Murray return 0; 80511b41d2SMark Murray case B50: 81511b41d2SMark Murray return 50; 82511b41d2SMark Murray case B75: 83511b41d2SMark Murray return 75; 84511b41d2SMark Murray case B110: 85511b41d2SMark Murray return 110; 86511b41d2SMark Murray case B134: 87511b41d2SMark Murray return 134; 88511b41d2SMark Murray case B150: 89511b41d2SMark Murray return 150; 90511b41d2SMark Murray case B200: 91511b41d2SMark Murray return 200; 92511b41d2SMark Murray case B300: 93511b41d2SMark Murray return 300; 94511b41d2SMark Murray case B600: 95511b41d2SMark Murray return 600; 96511b41d2SMark Murray case B1200: 97511b41d2SMark Murray return 1200; 98511b41d2SMark Murray case B1800: 99511b41d2SMark Murray return 1800; 100511b41d2SMark Murray case B2400: 101511b41d2SMark Murray return 2400; 102511b41d2SMark Murray case B4800: 103511b41d2SMark Murray return 4800; 104511b41d2SMark Murray case B9600: 105511b41d2SMark Murray return 9600; 106511b41d2SMark Murray 107511b41d2SMark Murray #ifdef B19200 108511b41d2SMark Murray case B19200: 109511b41d2SMark Murray return 19200; 110511b41d2SMark Murray #else /* B19200 */ 111511b41d2SMark Murray #ifdef EXTA 112511b41d2SMark Murray case EXTA: 113511b41d2SMark Murray return 19200; 114511b41d2SMark Murray #endif /* EXTA */ 115511b41d2SMark Murray #endif /* B19200 */ 116511b41d2SMark Murray 117511b41d2SMark Murray #ifdef B38400 118511b41d2SMark Murray case B38400: 119511b41d2SMark Murray return 38400; 120511b41d2SMark Murray #else /* B38400 */ 121511b41d2SMark Murray #ifdef EXTB 122511b41d2SMark Murray case EXTB: 123511b41d2SMark Murray return 38400; 124511b41d2SMark Murray #endif /* EXTB */ 125511b41d2SMark Murray #endif /* B38400 */ 126511b41d2SMark Murray 127511b41d2SMark Murray #ifdef B7200 128511b41d2SMark Murray case B7200: 129511b41d2SMark Murray return 7200; 130511b41d2SMark Murray #endif /* B7200 */ 131511b41d2SMark Murray #ifdef B14400 132511b41d2SMark Murray case B14400: 133511b41d2SMark Murray return 14400; 134511b41d2SMark Murray #endif /* B14400 */ 135511b41d2SMark Murray #ifdef B28800 136511b41d2SMark Murray case B28800: 137511b41d2SMark Murray return 28800; 138511b41d2SMark Murray #endif /* B28800 */ 139511b41d2SMark Murray #ifdef B57600 140511b41d2SMark Murray case B57600: 141511b41d2SMark Murray return 57600; 142511b41d2SMark Murray #endif /* B57600 */ 143511b41d2SMark Murray #ifdef B76800 144511b41d2SMark Murray case B76800: 145511b41d2SMark Murray return 76800; 146511b41d2SMark Murray #endif /* B76800 */ 147511b41d2SMark Murray #ifdef B115200 148511b41d2SMark Murray case B115200: 149511b41d2SMark Murray return 115200; 150511b41d2SMark Murray #endif /* B115200 */ 151511b41d2SMark Murray #ifdef B230400 152511b41d2SMark Murray case B230400: 153511b41d2SMark Murray return 230400; 154511b41d2SMark Murray #endif /* B230400 */ 155511b41d2SMark Murray default: 156511b41d2SMark Murray return 9600; 157511b41d2SMark Murray } 158511b41d2SMark Murray } 159511b41d2SMark Murray 160511b41d2SMark Murray /* 161511b41d2SMark Murray * Converts a numeric baud rate to a POSIX speed_t. 162511b41d2SMark Murray */ 163511b41d2SMark Murray static speed_t 164511b41d2SMark Murray baud_to_speed(int baud) 165511b41d2SMark Murray { 166511b41d2SMark Murray switch (baud) { 167511b41d2SMark Murray case 0: 168511b41d2SMark Murray return B0; 169511b41d2SMark Murray case 50: 170511b41d2SMark Murray return B50; 171511b41d2SMark Murray case 75: 172511b41d2SMark Murray return B75; 173511b41d2SMark Murray case 110: 174511b41d2SMark Murray return B110; 175511b41d2SMark Murray case 134: 176511b41d2SMark Murray return B134; 177511b41d2SMark Murray case 150: 178511b41d2SMark Murray return B150; 179511b41d2SMark Murray case 200: 180511b41d2SMark Murray return B200; 181511b41d2SMark Murray case 300: 182511b41d2SMark Murray return B300; 183511b41d2SMark Murray case 600: 184511b41d2SMark Murray return B600; 185511b41d2SMark Murray case 1200: 186511b41d2SMark Murray return B1200; 187511b41d2SMark Murray case 1800: 188511b41d2SMark Murray return B1800; 189511b41d2SMark Murray case 2400: 190511b41d2SMark Murray return B2400; 191511b41d2SMark Murray case 4800: 192511b41d2SMark Murray return B4800; 193511b41d2SMark Murray case 9600: 194511b41d2SMark Murray return B9600; 195511b41d2SMark Murray 196511b41d2SMark Murray #ifdef B19200 197511b41d2SMark Murray case 19200: 198511b41d2SMark Murray return B19200; 199511b41d2SMark Murray #else /* B19200 */ 200511b41d2SMark Murray #ifdef EXTA 201511b41d2SMark Murray case 19200: 202511b41d2SMark Murray return EXTA; 203511b41d2SMark Murray #endif /* EXTA */ 204511b41d2SMark Murray #endif /* B19200 */ 205511b41d2SMark Murray 206511b41d2SMark Murray #ifdef B38400 207511b41d2SMark Murray case 38400: 208511b41d2SMark Murray return B38400; 209511b41d2SMark Murray #else /* B38400 */ 210511b41d2SMark Murray #ifdef EXTB 211511b41d2SMark Murray case 38400: 212511b41d2SMark Murray return EXTB; 213511b41d2SMark Murray #endif /* EXTB */ 214511b41d2SMark Murray #endif /* B38400 */ 215511b41d2SMark Murray 216511b41d2SMark Murray #ifdef B7200 217511b41d2SMark Murray case 7200: 218511b41d2SMark Murray return B7200; 219511b41d2SMark Murray #endif /* B7200 */ 220511b41d2SMark Murray #ifdef B14400 221511b41d2SMark Murray case 14400: 222511b41d2SMark Murray return B14400; 223511b41d2SMark Murray #endif /* B14400 */ 224511b41d2SMark Murray #ifdef B28800 225511b41d2SMark Murray case 28800: 226511b41d2SMark Murray return B28800; 227511b41d2SMark Murray #endif /* B28800 */ 228511b41d2SMark Murray #ifdef B57600 229511b41d2SMark Murray case 57600: 230511b41d2SMark Murray return B57600; 231511b41d2SMark Murray #endif /* B57600 */ 232511b41d2SMark Murray #ifdef B76800 233511b41d2SMark Murray case 76800: 234511b41d2SMark Murray return B76800; 235511b41d2SMark Murray #endif /* B76800 */ 236511b41d2SMark Murray #ifdef B115200 237511b41d2SMark Murray case 115200: 238511b41d2SMark Murray return B115200; 239511b41d2SMark Murray #endif /* B115200 */ 240511b41d2SMark Murray #ifdef B230400 241511b41d2SMark Murray case 230400: 242511b41d2SMark Murray return B230400; 243511b41d2SMark Murray #endif /* B230400 */ 244511b41d2SMark Murray default: 245511b41d2SMark Murray return B9600; 246511b41d2SMark Murray } 247511b41d2SMark Murray } 248511b41d2SMark Murray 249511b41d2SMark Murray /* 250043840dfSDag-Erling Smørgrav * Encode a special character into SSH line format. 251043840dfSDag-Erling Smørgrav */ 252043840dfSDag-Erling Smørgrav static u_int 253043840dfSDag-Erling Smørgrav special_char_encode(cc_t c) 254043840dfSDag-Erling Smørgrav { 255043840dfSDag-Erling Smørgrav #ifdef _POSIX_VDISABLE 256043840dfSDag-Erling Smørgrav if (c == _POSIX_VDISABLE) 257043840dfSDag-Erling Smørgrav return 255; 258043840dfSDag-Erling Smørgrav #endif /* _POSIX_VDISABLE */ 259043840dfSDag-Erling Smørgrav return c; 260043840dfSDag-Erling Smørgrav } 261043840dfSDag-Erling Smørgrav 262043840dfSDag-Erling Smørgrav /* 263043840dfSDag-Erling Smørgrav * Decode a special character from SSH line format. 264043840dfSDag-Erling Smørgrav */ 265043840dfSDag-Erling Smørgrav static cc_t 266043840dfSDag-Erling Smørgrav special_char_decode(u_int c) 267043840dfSDag-Erling Smørgrav { 268043840dfSDag-Erling Smørgrav #ifdef _POSIX_VDISABLE 269043840dfSDag-Erling Smørgrav if (c == 255) 270043840dfSDag-Erling Smørgrav return _POSIX_VDISABLE; 271043840dfSDag-Erling Smørgrav #endif /* _POSIX_VDISABLE */ 272043840dfSDag-Erling Smørgrav return c; 273043840dfSDag-Erling Smørgrav } 274043840dfSDag-Erling Smørgrav 275043840dfSDag-Erling Smørgrav /* 276511b41d2SMark Murray * Encodes terminal modes for the terminal referenced by fd 2771e8db6e2SBrian Feldman * or tiop in a portable manner, and appends the modes to a packet 278511b41d2SMark Murray * being constructed. 279511b41d2SMark Murray */ 280511b41d2SMark Murray void 2811e8db6e2SBrian Feldman tty_make_modes(int fd, struct termios *tiop) 282511b41d2SMark Murray { 283511b41d2SMark Murray struct termios tio; 284511b41d2SMark Murray int baud; 2851e8db6e2SBrian Feldman Buffer buf; 2861e8db6e2SBrian Feldman int tty_op_ospeed, tty_op_ispeed; 2871e8db6e2SBrian Feldman void (*put_arg)(Buffer *, u_int); 288511b41d2SMark Murray 2891e8db6e2SBrian Feldman buffer_init(&buf); 2901e8db6e2SBrian Feldman if (compat20) { 2911e8db6e2SBrian Feldman tty_op_ospeed = TTY_OP_OSPEED_PROTO2; 2921e8db6e2SBrian Feldman tty_op_ispeed = TTY_OP_ISPEED_PROTO2; 2931e8db6e2SBrian Feldman put_arg = buffer_put_int; 2941e8db6e2SBrian Feldman } else { 2951e8db6e2SBrian Feldman tty_op_ospeed = TTY_OP_OSPEED_PROTO1; 2961e8db6e2SBrian Feldman tty_op_ispeed = TTY_OP_ISPEED_PROTO1; 2971e8db6e2SBrian Feldman put_arg = (void (*)(Buffer *, u_int)) buffer_put_char; 298511b41d2SMark Murray } 2991e8db6e2SBrian Feldman 3001e8db6e2SBrian Feldman if (tiop == NULL) { 301d4af9e69SDag-Erling Smørgrav if (fd == -1) { 302d4af9e69SDag-Erling Smørgrav debug("tty_make_modes: no fd or tio"); 303d4af9e69SDag-Erling Smørgrav goto end; 304d4af9e69SDag-Erling Smørgrav } 3051e8db6e2SBrian Feldman if (tcgetattr(fd, &tio) == -1) { 306d95e11bfSDag-Erling Smørgrav logit("tcgetattr: %.100s", strerror(errno)); 3071e8db6e2SBrian Feldman goto end; 3081e8db6e2SBrian Feldman } 3091e8db6e2SBrian Feldman } else 3101e8db6e2SBrian Feldman tio = *tiop; 3111e8db6e2SBrian Feldman 312511b41d2SMark Murray /* Store input and output baud rates. */ 313511b41d2SMark Murray baud = speed_to_baud(cfgetospeed(&tio)); 314ae1f160dSDag-Erling Smørgrav debug3("tty_make_modes: ospeed %d", baud); 3151e8db6e2SBrian Feldman buffer_put_char(&buf, tty_op_ospeed); 3161e8db6e2SBrian Feldman buffer_put_int(&buf, baud); 317511b41d2SMark Murray baud = speed_to_baud(cfgetispeed(&tio)); 318ae1f160dSDag-Erling Smørgrav debug3("tty_make_modes: ispeed %d", baud); 3191e8db6e2SBrian Feldman buffer_put_char(&buf, tty_op_ispeed); 3201e8db6e2SBrian Feldman buffer_put_int(&buf, baud); 321511b41d2SMark Murray 322511b41d2SMark Murray /* Store values of mode flags. */ 323511b41d2SMark Murray #define TTYCHAR(NAME, OP) \ 3241e8db6e2SBrian Feldman buffer_put_char(&buf, OP); \ 325043840dfSDag-Erling Smørgrav put_arg(&buf, special_char_encode(tio.c_cc[NAME])); 3261e8db6e2SBrian Feldman 327511b41d2SMark Murray #define TTYMODE(NAME, FIELD, OP) \ 3281e8db6e2SBrian Feldman buffer_put_char(&buf, OP); \ 3291e8db6e2SBrian Feldman put_arg(&buf, ((tio.FIELD & NAME) != 0)); 330511b41d2SMark Murray 331511b41d2SMark Murray #include "ttymodes.h" 332511b41d2SMark Murray 333511b41d2SMark Murray #undef TTYCHAR 334511b41d2SMark Murray #undef TTYMODE 335511b41d2SMark Murray 3361e8db6e2SBrian Feldman end: 337511b41d2SMark Murray /* Mark end of mode data. */ 3381e8db6e2SBrian Feldman buffer_put_char(&buf, TTY_OP_END); 3391e8db6e2SBrian Feldman if (compat20) 3401e8db6e2SBrian Feldman packet_put_string(buffer_ptr(&buf), buffer_len(&buf)); 3411e8db6e2SBrian Feldman else 3421e8db6e2SBrian Feldman packet_put_raw(buffer_ptr(&buf), buffer_len(&buf)); 3431e8db6e2SBrian Feldman buffer_free(&buf); 344511b41d2SMark Murray } 345511b41d2SMark Murray 346511b41d2SMark Murray /* 347511b41d2SMark Murray * Decodes terminal modes for the terminal referenced by fd in a portable 348511b41d2SMark Murray * manner from a packet being read. 349511b41d2SMark Murray */ 350511b41d2SMark Murray void 351511b41d2SMark Murray tty_parse_modes(int fd, int *n_bytes_ptr) 352511b41d2SMark Murray { 353511b41d2SMark Murray struct termios tio; 354511b41d2SMark Murray int opcode, baud; 355511b41d2SMark Murray int n_bytes = 0; 356511b41d2SMark Murray int failure = 0; 3571e8db6e2SBrian Feldman u_int (*get_arg)(void); 358d4af9e69SDag-Erling Smørgrav int arg_size; 3591e8db6e2SBrian Feldman 3601e8db6e2SBrian Feldman if (compat20) { 3611e8db6e2SBrian Feldman *n_bytes_ptr = packet_get_int(); 362ae1f160dSDag-Erling Smørgrav debug3("tty_parse_modes: SSH2 n_bytes %d", *n_bytes_ptr); 3631e8db6e2SBrian Feldman if (*n_bytes_ptr == 0) 3641e8db6e2SBrian Feldman return; 3651e8db6e2SBrian Feldman get_arg = packet_get_int; 3661e8db6e2SBrian Feldman arg_size = 4; 3671e8db6e2SBrian Feldman } else { 3681e8db6e2SBrian Feldman get_arg = packet_get_char; 3691e8db6e2SBrian Feldman arg_size = 1; 3701e8db6e2SBrian Feldman } 371511b41d2SMark Murray 372511b41d2SMark Murray /* 373511b41d2SMark Murray * Get old attributes for the terminal. We will modify these 374511b41d2SMark Murray * flags. I am hoping that if there are any machine-specific 375511b41d2SMark Murray * modes, they will initially have reasonable values. 376511b41d2SMark Murray */ 3771e8db6e2SBrian Feldman if (tcgetattr(fd, &tio) == -1) { 378d95e11bfSDag-Erling Smørgrav logit("tcgetattr: %.100s", strerror(errno)); 379511b41d2SMark Murray failure = -1; 3801e8db6e2SBrian Feldman } 381511b41d2SMark Murray 382511b41d2SMark Murray for (;;) { 383511b41d2SMark Murray n_bytes += 1; 384511b41d2SMark Murray opcode = packet_get_char(); 385511b41d2SMark Murray switch (opcode) { 386511b41d2SMark Murray case TTY_OP_END: 387511b41d2SMark Murray goto set; 388511b41d2SMark Murray 3891e8db6e2SBrian Feldman /* XXX: future conflict possible */ 3901e8db6e2SBrian Feldman case TTY_OP_ISPEED_PROTO1: 3911e8db6e2SBrian Feldman case TTY_OP_ISPEED_PROTO2: 392511b41d2SMark Murray n_bytes += 4; 393511b41d2SMark Murray baud = packet_get_int(); 394ae1f160dSDag-Erling Smørgrav debug3("tty_parse_modes: ispeed %d", baud); 395761efaa7SDag-Erling Smørgrav if (failure != -1 && 396761efaa7SDag-Erling Smørgrav cfsetispeed(&tio, baud_to_speed(baud)) == -1) 397511b41d2SMark Murray error("cfsetispeed failed for %d", baud); 398511b41d2SMark Murray break; 399511b41d2SMark Murray 4001e8db6e2SBrian Feldman /* XXX: future conflict possible */ 4011e8db6e2SBrian Feldman case TTY_OP_OSPEED_PROTO1: 4021e8db6e2SBrian Feldman case TTY_OP_OSPEED_PROTO2: 403511b41d2SMark Murray n_bytes += 4; 404511b41d2SMark Murray baud = packet_get_int(); 405ae1f160dSDag-Erling Smørgrav debug3("tty_parse_modes: ospeed %d", baud); 406761efaa7SDag-Erling Smørgrav if (failure != -1 && 407761efaa7SDag-Erling Smørgrav cfsetospeed(&tio, baud_to_speed(baud)) == -1) 408511b41d2SMark Murray error("cfsetospeed failed for %d", baud); 409511b41d2SMark Murray break; 410511b41d2SMark Murray 411511b41d2SMark Murray #define TTYCHAR(NAME, OP) \ 412511b41d2SMark Murray case OP: \ 4131e8db6e2SBrian Feldman n_bytes += arg_size; \ 414043840dfSDag-Erling Smørgrav tio.c_cc[NAME] = special_char_decode(get_arg()); \ 415511b41d2SMark Murray break; 416511b41d2SMark Murray #define TTYMODE(NAME, FIELD, OP) \ 417511b41d2SMark Murray case OP: \ 4181e8db6e2SBrian Feldman n_bytes += arg_size; \ 419d4af9e69SDag-Erling Smørgrav if (get_arg()) \ 420511b41d2SMark Murray tio.FIELD |= NAME; \ 421511b41d2SMark Murray else \ 422511b41d2SMark Murray tio.FIELD &= ~NAME; \ 423511b41d2SMark Murray break; 424511b41d2SMark Murray 425511b41d2SMark Murray #include "ttymodes.h" 426511b41d2SMark Murray 427511b41d2SMark Murray #undef TTYCHAR 428511b41d2SMark Murray #undef TTYMODE 429511b41d2SMark Murray 430511b41d2SMark Murray default: 431511b41d2SMark Murray debug("Ignoring unsupported tty mode opcode %d (0x%x)", 432511b41d2SMark Murray opcode, opcode); 4331e8db6e2SBrian Feldman if (!compat20) { 434511b41d2SMark Murray /* 4351e8db6e2SBrian Feldman * SSH1: 4361e8db6e2SBrian Feldman * Opcodes 1 to 127 are defined to have 437511b41d2SMark Murray * a one-byte argument. 438511b41d2SMark Murray * Opcodes 128 to 159 are defined to have 439511b41d2SMark Murray * an integer argument. 440511b41d2SMark Murray */ 4411e8db6e2SBrian Feldman if (opcode > 0 && opcode < 128) { 4421e8db6e2SBrian Feldman n_bytes += 1; 4431e8db6e2SBrian Feldman (void) packet_get_char(); 4441e8db6e2SBrian Feldman break; 4451e8db6e2SBrian Feldman } else if (opcode >= 128 && opcode < 160) { 446511b41d2SMark Murray n_bytes += 4; 447511b41d2SMark Murray (void) packet_get_int(); 448511b41d2SMark Murray break; 4491e8db6e2SBrian Feldman } else { 450511b41d2SMark Murray /* 451511b41d2SMark Murray * It is a truly undefined opcode (160 to 255). 452511b41d2SMark Murray * We have no idea about its arguments. So we 453761efaa7SDag-Erling Smørgrav * must stop parsing. Note that some data 454761efaa7SDag-Erling Smørgrav * may be left in the packet; hopefully there 455761efaa7SDag-Erling Smørgrav * is nothing more coming after the mode data. 456511b41d2SMark Murray */ 457761efaa7SDag-Erling Smørgrav logit("parse_tty_modes: unknown opcode %d", 458761efaa7SDag-Erling Smørgrav opcode); 459511b41d2SMark Murray goto set; 460511b41d2SMark Murray } 4611e8db6e2SBrian Feldman } else { 4621e8db6e2SBrian Feldman /* 4631e8db6e2SBrian Feldman * SSH2: 4641e8db6e2SBrian Feldman * Opcodes 1 to 159 are defined to have 4651e8db6e2SBrian Feldman * a uint32 argument. 4661e8db6e2SBrian Feldman * Opcodes 160 to 255 are undefined and 4671e8db6e2SBrian Feldman * cause parsing to stop. 4681e8db6e2SBrian Feldman */ 4691e8db6e2SBrian Feldman if (opcode > 0 && opcode < 160) { 4701e8db6e2SBrian Feldman n_bytes += 4; 4711e8db6e2SBrian Feldman (void) packet_get_int(); 4721e8db6e2SBrian Feldman break; 4731e8db6e2SBrian Feldman } else { 474761efaa7SDag-Erling Smørgrav logit("parse_tty_modes: unknown opcode %d", 475761efaa7SDag-Erling Smørgrav opcode); 4761e8db6e2SBrian Feldman goto set; 4771e8db6e2SBrian Feldman } 4781e8db6e2SBrian Feldman } 4791e8db6e2SBrian Feldman } 480511b41d2SMark Murray } 481511b41d2SMark Murray 482511b41d2SMark Murray set: 483511b41d2SMark Murray if (*n_bytes_ptr != n_bytes) { 484511b41d2SMark Murray *n_bytes_ptr = n_bytes; 485d95e11bfSDag-Erling Smørgrav logit("parse_tty_modes: n_bytes_ptr != n_bytes: %d %d", 4861e8db6e2SBrian Feldman *n_bytes_ptr, n_bytes); 487511b41d2SMark Murray return; /* Don't process bytes passed */ 488511b41d2SMark Murray } 489511b41d2SMark Murray if (failure == -1) 4901e8db6e2SBrian Feldman return; /* Packet parsed ok but tcgetattr() failed */ 491511b41d2SMark Murray 492511b41d2SMark Murray /* Set the new modes for the terminal. */ 4931e8db6e2SBrian Feldman if (tcsetattr(fd, TCSANOW, &tio) == -1) 494d95e11bfSDag-Erling Smørgrav logit("Setting tty modes failed: %.100s", strerror(errno)); 495511b41d2SMark Murray } 496