1*190cef3dSDag-Erling Smørgrav /* $OpenBSD: ttymodes.c,v 1.34 2018/07/09 21:20:26 markus 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" 58*190cef3dSDag-Erling Smørgrav #include "sshbuf.h" 59*190cef3dSDag-Erling Smørgrav #include "ssherr.h" 60511b41d2SMark Murray 61511b41d2SMark Murray #define TTY_OP_END 0 621e8db6e2SBrian Feldman /* 634f52dfbbSDag-Erling Smørgrav * uint32 (u_int) follows speed. 641e8db6e2SBrian Feldman */ 654f52dfbbSDag-Erling Smørgrav #define TTY_OP_ISPEED 128 664f52dfbbSDag-Erling Smørgrav #define TTY_OP_OSPEED 129 67511b41d2SMark Murray 68511b41d2SMark Murray /* 69511b41d2SMark Murray * Converts POSIX speed_t to a baud rate. The values of the 70511b41d2SMark Murray * constants for speed_t are not themselves portable. 71511b41d2SMark Murray */ 72511b41d2SMark Murray static int 73511b41d2SMark Murray speed_to_baud(speed_t speed) 74511b41d2SMark Murray { 75511b41d2SMark Murray switch (speed) { 76511b41d2SMark Murray case B0: 77511b41d2SMark Murray return 0; 78511b41d2SMark Murray case B50: 79511b41d2SMark Murray return 50; 80511b41d2SMark Murray case B75: 81511b41d2SMark Murray return 75; 82511b41d2SMark Murray case B110: 83511b41d2SMark Murray return 110; 84511b41d2SMark Murray case B134: 85511b41d2SMark Murray return 134; 86511b41d2SMark Murray case B150: 87511b41d2SMark Murray return 150; 88511b41d2SMark Murray case B200: 89511b41d2SMark Murray return 200; 90511b41d2SMark Murray case B300: 91511b41d2SMark Murray return 300; 92511b41d2SMark Murray case B600: 93511b41d2SMark Murray return 600; 94511b41d2SMark Murray case B1200: 95511b41d2SMark Murray return 1200; 96511b41d2SMark Murray case B1800: 97511b41d2SMark Murray return 1800; 98511b41d2SMark Murray case B2400: 99511b41d2SMark Murray return 2400; 100511b41d2SMark Murray case B4800: 101511b41d2SMark Murray return 4800; 102511b41d2SMark Murray case B9600: 103511b41d2SMark Murray return 9600; 104511b41d2SMark Murray 105511b41d2SMark Murray #ifdef B19200 106511b41d2SMark Murray case B19200: 107511b41d2SMark Murray return 19200; 108511b41d2SMark Murray #else /* B19200 */ 109511b41d2SMark Murray #ifdef EXTA 110511b41d2SMark Murray case EXTA: 111511b41d2SMark Murray return 19200; 112511b41d2SMark Murray #endif /* EXTA */ 113511b41d2SMark Murray #endif /* B19200 */ 114511b41d2SMark Murray 115511b41d2SMark Murray #ifdef B38400 116511b41d2SMark Murray case B38400: 117511b41d2SMark Murray return 38400; 118511b41d2SMark Murray #else /* B38400 */ 119511b41d2SMark Murray #ifdef EXTB 120511b41d2SMark Murray case EXTB: 121511b41d2SMark Murray return 38400; 122511b41d2SMark Murray #endif /* EXTB */ 123511b41d2SMark Murray #endif /* B38400 */ 124511b41d2SMark Murray 125511b41d2SMark Murray #ifdef B7200 126511b41d2SMark Murray case B7200: 127511b41d2SMark Murray return 7200; 128511b41d2SMark Murray #endif /* B7200 */ 129511b41d2SMark Murray #ifdef B14400 130511b41d2SMark Murray case B14400: 131511b41d2SMark Murray return 14400; 132511b41d2SMark Murray #endif /* B14400 */ 133511b41d2SMark Murray #ifdef B28800 134511b41d2SMark Murray case B28800: 135511b41d2SMark Murray return 28800; 136511b41d2SMark Murray #endif /* B28800 */ 137511b41d2SMark Murray #ifdef B57600 138511b41d2SMark Murray case B57600: 139511b41d2SMark Murray return 57600; 140511b41d2SMark Murray #endif /* B57600 */ 141511b41d2SMark Murray #ifdef B76800 142511b41d2SMark Murray case B76800: 143511b41d2SMark Murray return 76800; 144511b41d2SMark Murray #endif /* B76800 */ 145511b41d2SMark Murray #ifdef B115200 146511b41d2SMark Murray case B115200: 147511b41d2SMark Murray return 115200; 148511b41d2SMark Murray #endif /* B115200 */ 149511b41d2SMark Murray #ifdef B230400 150511b41d2SMark Murray case B230400: 151511b41d2SMark Murray return 230400; 152511b41d2SMark Murray #endif /* B230400 */ 153511b41d2SMark Murray default: 154511b41d2SMark Murray return 9600; 155511b41d2SMark Murray } 156511b41d2SMark Murray } 157511b41d2SMark Murray 158511b41d2SMark Murray /* 159511b41d2SMark Murray * Converts a numeric baud rate to a POSIX speed_t. 160511b41d2SMark Murray */ 161511b41d2SMark Murray static speed_t 162511b41d2SMark Murray baud_to_speed(int baud) 163511b41d2SMark Murray { 164511b41d2SMark Murray switch (baud) { 165511b41d2SMark Murray case 0: 166511b41d2SMark Murray return B0; 167511b41d2SMark Murray case 50: 168511b41d2SMark Murray return B50; 169511b41d2SMark Murray case 75: 170511b41d2SMark Murray return B75; 171511b41d2SMark Murray case 110: 172511b41d2SMark Murray return B110; 173511b41d2SMark Murray case 134: 174511b41d2SMark Murray return B134; 175511b41d2SMark Murray case 150: 176511b41d2SMark Murray return B150; 177511b41d2SMark Murray case 200: 178511b41d2SMark Murray return B200; 179511b41d2SMark Murray case 300: 180511b41d2SMark Murray return B300; 181511b41d2SMark Murray case 600: 182511b41d2SMark Murray return B600; 183511b41d2SMark Murray case 1200: 184511b41d2SMark Murray return B1200; 185511b41d2SMark Murray case 1800: 186511b41d2SMark Murray return B1800; 187511b41d2SMark Murray case 2400: 188511b41d2SMark Murray return B2400; 189511b41d2SMark Murray case 4800: 190511b41d2SMark Murray return B4800; 191511b41d2SMark Murray case 9600: 192511b41d2SMark Murray return B9600; 193511b41d2SMark Murray 194511b41d2SMark Murray #ifdef B19200 195511b41d2SMark Murray case 19200: 196511b41d2SMark Murray return B19200; 197511b41d2SMark Murray #else /* B19200 */ 198511b41d2SMark Murray #ifdef EXTA 199511b41d2SMark Murray case 19200: 200511b41d2SMark Murray return EXTA; 201511b41d2SMark Murray #endif /* EXTA */ 202511b41d2SMark Murray #endif /* B19200 */ 203511b41d2SMark Murray 204511b41d2SMark Murray #ifdef B38400 205511b41d2SMark Murray case 38400: 206511b41d2SMark Murray return B38400; 207511b41d2SMark Murray #else /* B38400 */ 208511b41d2SMark Murray #ifdef EXTB 209511b41d2SMark Murray case 38400: 210511b41d2SMark Murray return EXTB; 211511b41d2SMark Murray #endif /* EXTB */ 212511b41d2SMark Murray #endif /* B38400 */ 213511b41d2SMark Murray 214511b41d2SMark Murray #ifdef B7200 215511b41d2SMark Murray case 7200: 216511b41d2SMark Murray return B7200; 217511b41d2SMark Murray #endif /* B7200 */ 218511b41d2SMark Murray #ifdef B14400 219511b41d2SMark Murray case 14400: 220511b41d2SMark Murray return B14400; 221511b41d2SMark Murray #endif /* B14400 */ 222511b41d2SMark Murray #ifdef B28800 223511b41d2SMark Murray case 28800: 224511b41d2SMark Murray return B28800; 225511b41d2SMark Murray #endif /* B28800 */ 226511b41d2SMark Murray #ifdef B57600 227511b41d2SMark Murray case 57600: 228511b41d2SMark Murray return B57600; 229511b41d2SMark Murray #endif /* B57600 */ 230511b41d2SMark Murray #ifdef B76800 231511b41d2SMark Murray case 76800: 232511b41d2SMark Murray return B76800; 233511b41d2SMark Murray #endif /* B76800 */ 234511b41d2SMark Murray #ifdef B115200 235511b41d2SMark Murray case 115200: 236511b41d2SMark Murray return B115200; 237511b41d2SMark Murray #endif /* B115200 */ 238511b41d2SMark Murray #ifdef B230400 239511b41d2SMark Murray case 230400: 240511b41d2SMark Murray return B230400; 241511b41d2SMark Murray #endif /* B230400 */ 242511b41d2SMark Murray default: 243511b41d2SMark Murray return B9600; 244511b41d2SMark Murray } 245511b41d2SMark Murray } 246511b41d2SMark Murray 247511b41d2SMark Murray /* 248043840dfSDag-Erling Smørgrav * Encode a special character into SSH line format. 249043840dfSDag-Erling Smørgrav */ 250043840dfSDag-Erling Smørgrav static u_int 251043840dfSDag-Erling Smørgrav special_char_encode(cc_t c) 252043840dfSDag-Erling Smørgrav { 253043840dfSDag-Erling Smørgrav #ifdef _POSIX_VDISABLE 254043840dfSDag-Erling Smørgrav if (c == _POSIX_VDISABLE) 255043840dfSDag-Erling Smørgrav return 255; 256043840dfSDag-Erling Smørgrav #endif /* _POSIX_VDISABLE */ 257043840dfSDag-Erling Smørgrav return c; 258043840dfSDag-Erling Smørgrav } 259043840dfSDag-Erling Smørgrav 260043840dfSDag-Erling Smørgrav /* 261043840dfSDag-Erling Smørgrav * Decode a special character from SSH line format. 262043840dfSDag-Erling Smørgrav */ 263043840dfSDag-Erling Smørgrav static cc_t 264043840dfSDag-Erling Smørgrav special_char_decode(u_int c) 265043840dfSDag-Erling Smørgrav { 266043840dfSDag-Erling Smørgrav #ifdef _POSIX_VDISABLE 267043840dfSDag-Erling Smørgrav if (c == 255) 268043840dfSDag-Erling Smørgrav return _POSIX_VDISABLE; 269043840dfSDag-Erling Smørgrav #endif /* _POSIX_VDISABLE */ 270043840dfSDag-Erling Smørgrav return c; 271043840dfSDag-Erling Smørgrav } 272043840dfSDag-Erling Smørgrav 273043840dfSDag-Erling Smørgrav /* 274511b41d2SMark Murray * Encodes terminal modes for the terminal referenced by fd 2751e8db6e2SBrian Feldman * or tiop in a portable manner, and appends the modes to a packet 276511b41d2SMark Murray * being constructed. 277511b41d2SMark Murray */ 278511b41d2SMark Murray void 279*190cef3dSDag-Erling Smørgrav ssh_tty_make_modes(struct ssh *ssh, int fd, struct termios *tiop) 280511b41d2SMark Murray { 281511b41d2SMark Murray struct termios tio; 282*190cef3dSDag-Erling Smørgrav struct sshbuf *buf; 283*190cef3dSDag-Erling Smørgrav int r, ibaud, obaud; 284511b41d2SMark Murray 285*190cef3dSDag-Erling Smørgrav if ((buf = sshbuf_new()) == NULL) 286*190cef3dSDag-Erling Smørgrav fatal("%s: sshbuf_new failed", __func__); 2871e8db6e2SBrian Feldman 2881e8db6e2SBrian Feldman if (tiop == NULL) { 289d4af9e69SDag-Erling Smørgrav if (fd == -1) { 290*190cef3dSDag-Erling Smørgrav debug("%s: no fd or tio", __func__); 291d4af9e69SDag-Erling Smørgrav goto end; 292d4af9e69SDag-Erling Smørgrav } 2931e8db6e2SBrian Feldman if (tcgetattr(fd, &tio) == -1) { 294d95e11bfSDag-Erling Smørgrav logit("tcgetattr: %.100s", strerror(errno)); 2951e8db6e2SBrian Feldman goto end; 2961e8db6e2SBrian Feldman } 2971e8db6e2SBrian Feldman } else 2981e8db6e2SBrian Feldman tio = *tiop; 2991e8db6e2SBrian Feldman 300511b41d2SMark Murray /* Store input and output baud rates. */ 301*190cef3dSDag-Erling Smørgrav obaud = speed_to_baud(cfgetospeed(&tio)); 302*190cef3dSDag-Erling Smørgrav ibaud = speed_to_baud(cfgetispeed(&tio)); 303*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_u8(buf, TTY_OP_OSPEED)) != 0 || 304*190cef3dSDag-Erling Smørgrav (r = sshbuf_put_u32(buf, obaud)) != 0 || 305*190cef3dSDag-Erling Smørgrav (r = sshbuf_put_u8(buf, TTY_OP_ISPEED)) != 0 || 306*190cef3dSDag-Erling Smørgrav (r = sshbuf_put_u32(buf, ibaud)) != 0) 307*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); 308511b41d2SMark Murray 309511b41d2SMark Murray /* Store values of mode flags. */ 310511b41d2SMark Murray #define TTYCHAR(NAME, OP) \ 311*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_u8(buf, OP)) != 0 || \ 312*190cef3dSDag-Erling Smørgrav (r = sshbuf_put_u32(buf, \ 313*190cef3dSDag-Erling Smørgrav special_char_encode(tio.c_cc[NAME]))) != 0) \ 314*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); \ 3151e8db6e2SBrian Feldman 31647dd1d1bSDag-Erling Smørgrav #define SSH_TTYMODE_IUTF8 42 /* for SSH_BUG_UTF8TTYMODE */ 31747dd1d1bSDag-Erling Smørgrav 318511b41d2SMark Murray #define TTYMODE(NAME, FIELD, OP) \ 31947dd1d1bSDag-Erling Smørgrav if (OP == SSH_TTYMODE_IUTF8 && (datafellows & SSH_BUG_UTF8TTYMODE)) { \ 32047dd1d1bSDag-Erling Smørgrav debug3("%s: SSH_BUG_UTF8TTYMODE", __func__); \ 321*190cef3dSDag-Erling Smørgrav } else if ((r = sshbuf_put_u8(buf, OP)) != 0 || \ 322*190cef3dSDag-Erling Smørgrav (r = sshbuf_put_u32(buf, ((tio.FIELD & NAME) != 0))) != 0) \ 323*190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r)); \ 324511b41d2SMark Murray 325511b41d2SMark Murray #include "ttymodes.h" 326511b41d2SMark Murray 327511b41d2SMark Murray #undef TTYCHAR 328511b41d2SMark Murray #undef TTYMODE 329511b41d2SMark Murray 3301e8db6e2SBrian Feldman end: 331511b41d2SMark Murray /* Mark end of mode data. */ 332*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_u8(buf, TTY_OP_END)) != 0 || 333*190cef3dSDag-Erling Smørgrav (r = sshpkt_put_stringb(ssh, buf)) != 0) 334*190cef3dSDag-Erling Smørgrav fatal("%s: packet error: %s", __func__, ssh_err(r)); 335*190cef3dSDag-Erling Smørgrav sshbuf_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 343*190cef3dSDag-Erling Smørgrav ssh_tty_parse_modes(struct ssh *ssh, int fd) 344511b41d2SMark Murray { 345511b41d2SMark Murray struct termios tio; 346*190cef3dSDag-Erling Smørgrav struct sshbuf *buf; 347*190cef3dSDag-Erling Smørgrav const u_char *data; 348*190cef3dSDag-Erling Smørgrav u_char opcode; 349*190cef3dSDag-Erling Smørgrav u_int baud, u; 350*190cef3dSDag-Erling Smørgrav int r, failure = 0; 351*190cef3dSDag-Erling Smørgrav size_t len; 3521e8db6e2SBrian Feldman 353*190cef3dSDag-Erling Smørgrav if ((r = sshpkt_get_string_direct(ssh, &data, &len)) != 0) 354*190cef3dSDag-Erling Smørgrav fatal("%s: packet error: %s", __func__, ssh_err(r)); 355*190cef3dSDag-Erling Smørgrav if (len == 0) 3561e8db6e2SBrian Feldman return; 357*190cef3dSDag-Erling Smørgrav if ((buf = sshbuf_from(data, len)) == NULL) { 358*190cef3dSDag-Erling Smørgrav error("%s: sshbuf_from failed", __func__); 359*190cef3dSDag-Erling Smørgrav return; 360*190cef3dSDag-Erling Smørgrav } 361511b41d2SMark Murray 362511b41d2SMark Murray /* 363511b41d2SMark Murray * Get old attributes for the terminal. We will modify these 364511b41d2SMark Murray * flags. I am hoping that if there are any machine-specific 365511b41d2SMark Murray * modes, they will initially have reasonable values. 366511b41d2SMark Murray */ 3671e8db6e2SBrian Feldman if (tcgetattr(fd, &tio) == -1) { 368d95e11bfSDag-Erling Smørgrav logit("tcgetattr: %.100s", strerror(errno)); 369511b41d2SMark Murray failure = -1; 3701e8db6e2SBrian Feldman } 371511b41d2SMark Murray 372*190cef3dSDag-Erling Smørgrav while (sshbuf_len(buf) > 0) { 373*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_u8(buf, &opcode)) != 0) 374*190cef3dSDag-Erling Smørgrav fatal("%s: packet error: %s", __func__, ssh_err(r)); 375511b41d2SMark Murray switch (opcode) { 376511b41d2SMark Murray case TTY_OP_END: 377511b41d2SMark Murray goto set; 378511b41d2SMark Murray 3794f52dfbbSDag-Erling Smørgrav case TTY_OP_ISPEED: 380*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_u32(buf, &baud)) != 0) 381*190cef3dSDag-Erling Smørgrav fatal("%s: packet error: %s", 382*190cef3dSDag-Erling Smørgrav __func__, ssh_err(r)); 383761efaa7SDag-Erling Smørgrav if (failure != -1 && 384761efaa7SDag-Erling Smørgrav cfsetispeed(&tio, baud_to_speed(baud)) == -1) 385511b41d2SMark Murray error("cfsetispeed failed for %d", baud); 386511b41d2SMark Murray break; 387511b41d2SMark Murray 3884f52dfbbSDag-Erling Smørgrav case TTY_OP_OSPEED: 389*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_u32(buf, &baud)) != 0) 390*190cef3dSDag-Erling Smørgrav fatal("%s: packet error: %s", 391*190cef3dSDag-Erling Smørgrav __func__, ssh_err(r)); 392761efaa7SDag-Erling Smørgrav if (failure != -1 && 393761efaa7SDag-Erling Smørgrav cfsetospeed(&tio, baud_to_speed(baud)) == -1) 394511b41d2SMark Murray error("cfsetospeed failed for %d", baud); 395511b41d2SMark Murray break; 396511b41d2SMark Murray 397511b41d2SMark Murray #define TTYCHAR(NAME, OP) \ 398511b41d2SMark Murray case OP: \ 399*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_u32(buf, &u)) != 0) \ 400*190cef3dSDag-Erling Smørgrav fatal("%s: packet error: %s", __func__, \ 401*190cef3dSDag-Erling Smørgrav ssh_err(r)); \ 402*190cef3dSDag-Erling Smørgrav tio.c_cc[NAME] = special_char_decode(u); \ 403511b41d2SMark Murray break; 404511b41d2SMark Murray #define TTYMODE(NAME, FIELD, OP) \ 405511b41d2SMark Murray case OP: \ 406*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_u32(buf, &u)) != 0) \ 407*190cef3dSDag-Erling Smørgrav fatal("%s: packet error: %s", __func__, \ 408*190cef3dSDag-Erling Smørgrav ssh_err(r)); \ 409*190cef3dSDag-Erling Smørgrav if (u) \ 410511b41d2SMark Murray tio.FIELD |= NAME; \ 411511b41d2SMark Murray else \ 412511b41d2SMark Murray tio.FIELD &= ~NAME; \ 413511b41d2SMark Murray break; 414511b41d2SMark Murray 415511b41d2SMark Murray #include "ttymodes.h" 416511b41d2SMark Murray 417511b41d2SMark Murray #undef TTYCHAR 418511b41d2SMark Murray #undef TTYMODE 419511b41d2SMark Murray 420511b41d2SMark Murray default: 421511b41d2SMark Murray debug("Ignoring unsupported tty mode opcode %d (0x%x)", 422511b41d2SMark Murray opcode, opcode); 4231e8db6e2SBrian Feldman /* 4241e8db6e2SBrian Feldman * SSH2: 4254f52dfbbSDag-Erling Smørgrav * Opcodes 1 to 159 are defined to have a uint32 4264f52dfbbSDag-Erling Smørgrav * argument. 4274f52dfbbSDag-Erling Smørgrav * Opcodes 160 to 255 are undefined and cause parsing 4284f52dfbbSDag-Erling Smørgrav * to stop. 4291e8db6e2SBrian Feldman */ 4301e8db6e2SBrian Feldman if (opcode > 0 && opcode < 160) { 431*190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_u32(buf, NULL)) != 0) 432*190cef3dSDag-Erling Smørgrav fatal("%s: packet error: %s", __func__, 433*190cef3dSDag-Erling Smørgrav ssh_err(r)); 4341e8db6e2SBrian Feldman break; 4351e8db6e2SBrian Feldman } else { 436*190cef3dSDag-Erling Smørgrav logit("%s: unknown opcode %d", __func__, 437761efaa7SDag-Erling Smørgrav opcode); 4381e8db6e2SBrian Feldman goto set; 4391e8db6e2SBrian Feldman } 4401e8db6e2SBrian Feldman } 4411e8db6e2SBrian Feldman } 442511b41d2SMark Murray 443511b41d2SMark Murray set: 444*190cef3dSDag-Erling Smørgrav len = sshbuf_len(buf); 445*190cef3dSDag-Erling Smørgrav sshbuf_free(buf); 446*190cef3dSDag-Erling Smørgrav if (len > 0) { 447*190cef3dSDag-Erling Smørgrav logit("%s: %zu bytes left", __func__, len); 448511b41d2SMark Murray return; /* Don't process bytes passed */ 449511b41d2SMark Murray } 450511b41d2SMark Murray if (failure == -1) 4511e8db6e2SBrian Feldman return; /* Packet parsed ok but tcgetattr() failed */ 452511b41d2SMark Murray 453511b41d2SMark Murray /* Set the new modes for the terminal. */ 4541e8db6e2SBrian Feldman if (tcsetattr(fd, TCSANOW, &tio) == -1) 455d95e11bfSDag-Erling Smørgrav logit("Setting tty modes failed: %.100s", strerror(errno)); 456511b41d2SMark Murray } 457