17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * Author: Tatu Ylonen <ylo@cs.hut.fi>
37c478bd9Sstevel@tonic-gate * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
47c478bd9Sstevel@tonic-gate * All rights reserved
57c478bd9Sstevel@tonic-gate *
67c478bd9Sstevel@tonic-gate * As far as I am concerned, the code I have written for this software
77c478bd9Sstevel@tonic-gate * can be used freely for any purpose. Any derived versions of this
87c478bd9Sstevel@tonic-gate * software must be clearly marked as such, and if the derived work is
97c478bd9Sstevel@tonic-gate * incompatible with the protocol description in the RFC file, it must be
107c478bd9Sstevel@tonic-gate * called by a name other than "ssh" or "Secure Shell".
117c478bd9Sstevel@tonic-gate */
127c478bd9Sstevel@tonic-gate
137c478bd9Sstevel@tonic-gate /*
147c478bd9Sstevel@tonic-gate * SSH2 tty modes support by Kevin Steves.
157c478bd9Sstevel@tonic-gate * Copyright (c) 2001 Kevin Steves. All rights reserved.
167c478bd9Sstevel@tonic-gate *
177c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without
187c478bd9Sstevel@tonic-gate * modification, are permitted provided that the following conditions
197c478bd9Sstevel@tonic-gate * are met:
207c478bd9Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright
217c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer.
227c478bd9Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright
237c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the
247c478bd9Sstevel@tonic-gate * documentation and/or other materials provided with the distribution.
257c478bd9Sstevel@tonic-gate *
267c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
277c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
287c478bd9Sstevel@tonic-gate * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
297c478bd9Sstevel@tonic-gate * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
307c478bd9Sstevel@tonic-gate * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
317c478bd9Sstevel@tonic-gate * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
327c478bd9Sstevel@tonic-gate * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
337c478bd9Sstevel@tonic-gate * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
347c478bd9Sstevel@tonic-gate * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
357c478bd9Sstevel@tonic-gate * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
367c478bd9Sstevel@tonic-gate */
37*de81e71eSTim Marsland
387c478bd9Sstevel@tonic-gate /*
39*de81e71eSTim Marsland * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
407c478bd9Sstevel@tonic-gate * Use is subject to license terms.
417c478bd9Sstevel@tonic-gate */
427c478bd9Sstevel@tonic-gate
437c478bd9Sstevel@tonic-gate /*
447c478bd9Sstevel@tonic-gate * Encoding and decoding of terminal modes in a portable way.
457c478bd9Sstevel@tonic-gate * Much of the format is defined in ttymodes.h; it is included multiple times
467c478bd9Sstevel@tonic-gate * into this file with the appropriate macro definitions to generate the
477c478bd9Sstevel@tonic-gate * suitable code.
487c478bd9Sstevel@tonic-gate */
497c478bd9Sstevel@tonic-gate
507c478bd9Sstevel@tonic-gate #include "includes.h"
517c478bd9Sstevel@tonic-gate RCSID("$OpenBSD: ttymodes.c,v 1.18 2002/06/19 00:27:55 deraadt Exp $");
527c478bd9Sstevel@tonic-gate
537c478bd9Sstevel@tonic-gate #include "packet.h"
547c478bd9Sstevel@tonic-gate #include "log.h"
557c478bd9Sstevel@tonic-gate #include "ssh1.h"
567c478bd9Sstevel@tonic-gate #include "compat.h"
577c478bd9Sstevel@tonic-gate #include "buffer.h"
587c478bd9Sstevel@tonic-gate #include "bufaux.h"
597c478bd9Sstevel@tonic-gate
607c478bd9Sstevel@tonic-gate #define TTY_OP_END 0
617c478bd9Sstevel@tonic-gate /*
627c478bd9Sstevel@tonic-gate * uint32 (u_int) follows speed in SSH1 and SSH2
637c478bd9Sstevel@tonic-gate */
647c478bd9Sstevel@tonic-gate #define TTY_OP_ISPEED_PROTO1 192
657c478bd9Sstevel@tonic-gate #define TTY_OP_OSPEED_PROTO1 193
667c478bd9Sstevel@tonic-gate #define TTY_OP_ISPEED_PROTO2 128
677c478bd9Sstevel@tonic-gate #define TTY_OP_OSPEED_PROTO2 129
687c478bd9Sstevel@tonic-gate
697c478bd9Sstevel@tonic-gate /*
707c478bd9Sstevel@tonic-gate * Converts POSIX speed_t to a baud rate. The values of the
717c478bd9Sstevel@tonic-gate * constants for speed_t are not themselves portable.
727c478bd9Sstevel@tonic-gate */
737c478bd9Sstevel@tonic-gate static int
speed_to_baud(speed_t speed)747c478bd9Sstevel@tonic-gate speed_to_baud(speed_t speed)
757c478bd9Sstevel@tonic-gate {
767c478bd9Sstevel@tonic-gate switch (speed) {
777c478bd9Sstevel@tonic-gate case B0:
787c478bd9Sstevel@tonic-gate return 0;
797c478bd9Sstevel@tonic-gate case B50:
807c478bd9Sstevel@tonic-gate return 50;
817c478bd9Sstevel@tonic-gate case B75:
827c478bd9Sstevel@tonic-gate return 75;
837c478bd9Sstevel@tonic-gate case B110:
847c478bd9Sstevel@tonic-gate return 110;
857c478bd9Sstevel@tonic-gate case B134:
867c478bd9Sstevel@tonic-gate return 134;
877c478bd9Sstevel@tonic-gate case B150:
887c478bd9Sstevel@tonic-gate return 150;
897c478bd9Sstevel@tonic-gate case B200:
907c478bd9Sstevel@tonic-gate return 200;
917c478bd9Sstevel@tonic-gate case B300:
927c478bd9Sstevel@tonic-gate return 300;
937c478bd9Sstevel@tonic-gate case B600:
947c478bd9Sstevel@tonic-gate return 600;
957c478bd9Sstevel@tonic-gate case B1200:
967c478bd9Sstevel@tonic-gate return 1200;
977c478bd9Sstevel@tonic-gate case B1800:
987c478bd9Sstevel@tonic-gate return 1800;
997c478bd9Sstevel@tonic-gate case B2400:
1007c478bd9Sstevel@tonic-gate return 2400;
1017c478bd9Sstevel@tonic-gate case B4800:
1027c478bd9Sstevel@tonic-gate return 4800;
1037c478bd9Sstevel@tonic-gate case B9600:
1047c478bd9Sstevel@tonic-gate return 9600;
1057c478bd9Sstevel@tonic-gate
1067c478bd9Sstevel@tonic-gate #ifdef B19200
1077c478bd9Sstevel@tonic-gate case B19200:
1087c478bd9Sstevel@tonic-gate return 19200;
1097c478bd9Sstevel@tonic-gate #else /* B19200 */
1107c478bd9Sstevel@tonic-gate #ifdef EXTA
1117c478bd9Sstevel@tonic-gate case EXTA:
1127c478bd9Sstevel@tonic-gate return 19200;
1137c478bd9Sstevel@tonic-gate #endif /* EXTA */
1147c478bd9Sstevel@tonic-gate #endif /* B19200 */
1157c478bd9Sstevel@tonic-gate
1167c478bd9Sstevel@tonic-gate #ifdef B38400
1177c478bd9Sstevel@tonic-gate case B38400:
1187c478bd9Sstevel@tonic-gate return 38400;
1197c478bd9Sstevel@tonic-gate #else /* B38400 */
1207c478bd9Sstevel@tonic-gate #ifdef EXTB
1217c478bd9Sstevel@tonic-gate case EXTB:
1227c478bd9Sstevel@tonic-gate return 38400;
1237c478bd9Sstevel@tonic-gate #endif /* EXTB */
1247c478bd9Sstevel@tonic-gate #endif /* B38400 */
1257c478bd9Sstevel@tonic-gate
1267c478bd9Sstevel@tonic-gate #ifdef B7200
1277c478bd9Sstevel@tonic-gate case B7200:
1287c478bd9Sstevel@tonic-gate return 7200;
1297c478bd9Sstevel@tonic-gate #endif /* B7200 */
1307c478bd9Sstevel@tonic-gate #ifdef B14400
1317c478bd9Sstevel@tonic-gate case B14400:
1327c478bd9Sstevel@tonic-gate return 14400;
1337c478bd9Sstevel@tonic-gate #endif /* B14400 */
1347c478bd9Sstevel@tonic-gate #ifdef B28800
1357c478bd9Sstevel@tonic-gate case B28800:
1367c478bd9Sstevel@tonic-gate return 28800;
1377c478bd9Sstevel@tonic-gate #endif /* B28800 */
1387c478bd9Sstevel@tonic-gate #ifdef B57600
1397c478bd9Sstevel@tonic-gate case B57600:
1407c478bd9Sstevel@tonic-gate return 57600;
1417c478bd9Sstevel@tonic-gate #endif /* B57600 */
1427c478bd9Sstevel@tonic-gate #ifdef B76800
1437c478bd9Sstevel@tonic-gate case B76800:
1447c478bd9Sstevel@tonic-gate return 76800;
1457c478bd9Sstevel@tonic-gate #endif /* B76800 */
1467c478bd9Sstevel@tonic-gate #ifdef B115200
1477c478bd9Sstevel@tonic-gate case B115200:
1487c478bd9Sstevel@tonic-gate return 115200;
1497c478bd9Sstevel@tonic-gate #endif /* B115200 */
1507c478bd9Sstevel@tonic-gate #ifdef B230400
1517c478bd9Sstevel@tonic-gate case B230400:
1527c478bd9Sstevel@tonic-gate return 230400;
1537c478bd9Sstevel@tonic-gate #endif /* B230400 */
154*de81e71eSTim Marsland #ifdef B460800
155*de81e71eSTim Marsland case B460800:
156*de81e71eSTim Marsland return 460800;
157*de81e71eSTim Marsland #endif /* B460800 */
158*de81e71eSTim Marsland #ifdef B921600
159*de81e71eSTim Marsland case B921600:
160*de81e71eSTim Marsland return 921600;
161*de81e71eSTim Marsland #endif /* B921600 */
1627c478bd9Sstevel@tonic-gate default:
1637c478bd9Sstevel@tonic-gate return 9600;
1647c478bd9Sstevel@tonic-gate }
1657c478bd9Sstevel@tonic-gate }
1667c478bd9Sstevel@tonic-gate
1677c478bd9Sstevel@tonic-gate /*
1687c478bd9Sstevel@tonic-gate * Converts a numeric baud rate to a POSIX speed_t.
1697c478bd9Sstevel@tonic-gate */
1707c478bd9Sstevel@tonic-gate static speed_t
baud_to_speed(int baud)1717c478bd9Sstevel@tonic-gate baud_to_speed(int baud)
1727c478bd9Sstevel@tonic-gate {
1737c478bd9Sstevel@tonic-gate switch (baud) {
1747c478bd9Sstevel@tonic-gate case 0:
1757c478bd9Sstevel@tonic-gate return B0;
1767c478bd9Sstevel@tonic-gate case 50:
1777c478bd9Sstevel@tonic-gate return B50;
1787c478bd9Sstevel@tonic-gate case 75:
1797c478bd9Sstevel@tonic-gate return B75;
1807c478bd9Sstevel@tonic-gate case 110:
1817c478bd9Sstevel@tonic-gate return B110;
1827c478bd9Sstevel@tonic-gate case 134:
1837c478bd9Sstevel@tonic-gate return B134;
1847c478bd9Sstevel@tonic-gate case 150:
1857c478bd9Sstevel@tonic-gate return B150;
1867c478bd9Sstevel@tonic-gate case 200:
1877c478bd9Sstevel@tonic-gate return B200;
1887c478bd9Sstevel@tonic-gate case 300:
1897c478bd9Sstevel@tonic-gate return B300;
1907c478bd9Sstevel@tonic-gate case 600:
1917c478bd9Sstevel@tonic-gate return B600;
1927c478bd9Sstevel@tonic-gate case 1200:
1937c478bd9Sstevel@tonic-gate return B1200;
1947c478bd9Sstevel@tonic-gate case 1800:
1957c478bd9Sstevel@tonic-gate return B1800;
1967c478bd9Sstevel@tonic-gate case 2400:
1977c478bd9Sstevel@tonic-gate return B2400;
1987c478bd9Sstevel@tonic-gate case 4800:
1997c478bd9Sstevel@tonic-gate return B4800;
2007c478bd9Sstevel@tonic-gate case 9600:
2017c478bd9Sstevel@tonic-gate return B9600;
2027c478bd9Sstevel@tonic-gate
2037c478bd9Sstevel@tonic-gate #ifdef B19200
2047c478bd9Sstevel@tonic-gate case 19200:
2057c478bd9Sstevel@tonic-gate return B19200;
2067c478bd9Sstevel@tonic-gate #else /* B19200 */
2077c478bd9Sstevel@tonic-gate #ifdef EXTA
2087c478bd9Sstevel@tonic-gate case 19200:
2097c478bd9Sstevel@tonic-gate return EXTA;
2107c478bd9Sstevel@tonic-gate #endif /* EXTA */
2117c478bd9Sstevel@tonic-gate #endif /* B19200 */
2127c478bd9Sstevel@tonic-gate
2137c478bd9Sstevel@tonic-gate #ifdef B38400
2147c478bd9Sstevel@tonic-gate case 38400:
2157c478bd9Sstevel@tonic-gate return B38400;
2167c478bd9Sstevel@tonic-gate #else /* B38400 */
2177c478bd9Sstevel@tonic-gate #ifdef EXTB
2187c478bd9Sstevel@tonic-gate case 38400:
2197c478bd9Sstevel@tonic-gate return EXTB;
2207c478bd9Sstevel@tonic-gate #endif /* EXTB */
2217c478bd9Sstevel@tonic-gate #endif /* B38400 */
2227c478bd9Sstevel@tonic-gate
2237c478bd9Sstevel@tonic-gate #ifdef B7200
2247c478bd9Sstevel@tonic-gate case 7200:
2257c478bd9Sstevel@tonic-gate return B7200;
2267c478bd9Sstevel@tonic-gate #endif /* B7200 */
2277c478bd9Sstevel@tonic-gate #ifdef B14400
2287c478bd9Sstevel@tonic-gate case 14400:
2297c478bd9Sstevel@tonic-gate return B14400;
2307c478bd9Sstevel@tonic-gate #endif /* B14400 */
2317c478bd9Sstevel@tonic-gate #ifdef B28800
2327c478bd9Sstevel@tonic-gate case 28800:
2337c478bd9Sstevel@tonic-gate return B28800;
2347c478bd9Sstevel@tonic-gate #endif /* B28800 */
2357c478bd9Sstevel@tonic-gate #ifdef B57600
2367c478bd9Sstevel@tonic-gate case 57600:
2377c478bd9Sstevel@tonic-gate return B57600;
2387c478bd9Sstevel@tonic-gate #endif /* B57600 */
2397c478bd9Sstevel@tonic-gate #ifdef B76800
2407c478bd9Sstevel@tonic-gate case 76800:
2417c478bd9Sstevel@tonic-gate return B76800;
2427c478bd9Sstevel@tonic-gate #endif /* B76800 */
2437c478bd9Sstevel@tonic-gate #ifdef B115200
2447c478bd9Sstevel@tonic-gate case 115200:
2457c478bd9Sstevel@tonic-gate return B115200;
2467c478bd9Sstevel@tonic-gate #endif /* B115200 */
2477c478bd9Sstevel@tonic-gate #ifdef B230400
2487c478bd9Sstevel@tonic-gate case 230400:
2497c478bd9Sstevel@tonic-gate return B230400;
2507c478bd9Sstevel@tonic-gate #endif /* B230400 */
251*de81e71eSTim Marsland #ifdef B460800
252*de81e71eSTim Marsland case 460800:
253*de81e71eSTim Marsland return B460800;
254*de81e71eSTim Marsland #endif /* B460800 */
255*de81e71eSTim Marsland #ifdef B921600
256*de81e71eSTim Marsland case 921600:
257*de81e71eSTim Marsland return B921600;
258*de81e71eSTim Marsland #endif /* B921600 */
2597c478bd9Sstevel@tonic-gate default:
2607c478bd9Sstevel@tonic-gate return B9600;
2617c478bd9Sstevel@tonic-gate }
2627c478bd9Sstevel@tonic-gate }
2637c478bd9Sstevel@tonic-gate
2647c478bd9Sstevel@tonic-gate /*
2657c478bd9Sstevel@tonic-gate * Encodes terminal modes for the terminal referenced by fd
2667c478bd9Sstevel@tonic-gate * or tiop in a portable manner, and appends the modes to a packet
2677c478bd9Sstevel@tonic-gate * being constructed.
2687c478bd9Sstevel@tonic-gate */
2697c478bd9Sstevel@tonic-gate void
tty_make_modes(int fd,struct termios * tiop)2707c478bd9Sstevel@tonic-gate tty_make_modes(int fd, struct termios *tiop)
2717c478bd9Sstevel@tonic-gate {
2727c478bd9Sstevel@tonic-gate struct termios tio;
2737c478bd9Sstevel@tonic-gate int baud;
2747c478bd9Sstevel@tonic-gate Buffer buf;
2757c478bd9Sstevel@tonic-gate int tty_op_ospeed, tty_op_ispeed;
2767c478bd9Sstevel@tonic-gate void (*put_arg)(Buffer *, u_int);
2777c478bd9Sstevel@tonic-gate
2787c478bd9Sstevel@tonic-gate buffer_init(&buf);
2797c478bd9Sstevel@tonic-gate if (compat20) {
2807c478bd9Sstevel@tonic-gate tty_op_ospeed = TTY_OP_OSPEED_PROTO2;
2817c478bd9Sstevel@tonic-gate tty_op_ispeed = TTY_OP_ISPEED_PROTO2;
2827c478bd9Sstevel@tonic-gate put_arg = buffer_put_int;
2837c478bd9Sstevel@tonic-gate } else {
2847c478bd9Sstevel@tonic-gate tty_op_ospeed = TTY_OP_OSPEED_PROTO1;
2857c478bd9Sstevel@tonic-gate tty_op_ispeed = TTY_OP_ISPEED_PROTO1;
2867c478bd9Sstevel@tonic-gate put_arg = (void (*)(Buffer *, u_int)) buffer_put_char;
2877c478bd9Sstevel@tonic-gate }
2887c478bd9Sstevel@tonic-gate
2897c478bd9Sstevel@tonic-gate if (tiop == NULL) {
2907c478bd9Sstevel@tonic-gate if (tcgetattr(fd, &tio) == -1) {
2917c478bd9Sstevel@tonic-gate log("tcgetattr: %.100s", strerror(errno));
2927c478bd9Sstevel@tonic-gate goto end;
2937c478bd9Sstevel@tonic-gate }
2947c478bd9Sstevel@tonic-gate } else
2957c478bd9Sstevel@tonic-gate tio = *tiop;
2967c478bd9Sstevel@tonic-gate
2977c478bd9Sstevel@tonic-gate /* Store input and output baud rates. */
2987c478bd9Sstevel@tonic-gate baud = speed_to_baud(cfgetospeed(&tio));
2997c478bd9Sstevel@tonic-gate debug3("tty_make_modes: ospeed %d", baud);
3007c478bd9Sstevel@tonic-gate buffer_put_char(&buf, tty_op_ospeed);
3017c478bd9Sstevel@tonic-gate buffer_put_int(&buf, baud);
3027c478bd9Sstevel@tonic-gate baud = speed_to_baud(cfgetispeed(&tio));
3037c478bd9Sstevel@tonic-gate debug3("tty_make_modes: ispeed %d", baud);
3047c478bd9Sstevel@tonic-gate buffer_put_char(&buf, tty_op_ispeed);
3057c478bd9Sstevel@tonic-gate buffer_put_int(&buf, baud);
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gate /* Store values of mode flags. */
3087c478bd9Sstevel@tonic-gate #define TTYCHAR(NAME, OP) \
3097c478bd9Sstevel@tonic-gate debug3("tty_make_modes: %d %d", OP, tio.c_cc[NAME]); \
3107c478bd9Sstevel@tonic-gate buffer_put_char(&buf, OP); \
3117c478bd9Sstevel@tonic-gate put_arg(&buf, tio.c_cc[NAME]);
3127c478bd9Sstevel@tonic-gate
3137c478bd9Sstevel@tonic-gate #define TTYMODE(NAME, FIELD, OP) \
3147c478bd9Sstevel@tonic-gate debug3("tty_make_modes: %d %d", OP, ((tio.FIELD & NAME) != 0)); \
3157c478bd9Sstevel@tonic-gate buffer_put_char(&buf, OP); \
3167c478bd9Sstevel@tonic-gate put_arg(&buf, ((tio.FIELD & NAME) != 0));
3177c478bd9Sstevel@tonic-gate
3187c478bd9Sstevel@tonic-gate #include "ttymodes.h"
3197c478bd9Sstevel@tonic-gate
3207c478bd9Sstevel@tonic-gate #undef TTYCHAR
3217c478bd9Sstevel@tonic-gate #undef TTYMODE
3227c478bd9Sstevel@tonic-gate
3237c478bd9Sstevel@tonic-gate end:
3247c478bd9Sstevel@tonic-gate /* Mark end of mode data. */
3257c478bd9Sstevel@tonic-gate buffer_put_char(&buf, TTY_OP_END);
3267c478bd9Sstevel@tonic-gate if (compat20)
3277c478bd9Sstevel@tonic-gate packet_put_string(buffer_ptr(&buf), buffer_len(&buf));
3287c478bd9Sstevel@tonic-gate else
3297c478bd9Sstevel@tonic-gate packet_put_raw(buffer_ptr(&buf), buffer_len(&buf));
3307c478bd9Sstevel@tonic-gate buffer_free(&buf);
3317c478bd9Sstevel@tonic-gate }
3327c478bd9Sstevel@tonic-gate
3337c478bd9Sstevel@tonic-gate /*
3347c478bd9Sstevel@tonic-gate * Decodes terminal modes for the terminal referenced by fd in a portable
3357c478bd9Sstevel@tonic-gate * manner from a packet being read.
3367c478bd9Sstevel@tonic-gate */
3377c478bd9Sstevel@tonic-gate void
tty_parse_modes(int fd,int * n_bytes_ptr)3387c478bd9Sstevel@tonic-gate tty_parse_modes(int fd, int *n_bytes_ptr)
3397c478bd9Sstevel@tonic-gate {
3407c478bd9Sstevel@tonic-gate struct termios tio;
3417c478bd9Sstevel@tonic-gate int opcode, baud;
3427c478bd9Sstevel@tonic-gate int n_bytes = 0;
3437c478bd9Sstevel@tonic-gate int failure = 0;
3447c478bd9Sstevel@tonic-gate u_int (*get_arg)(void);
3457c478bd9Sstevel@tonic-gate int arg, arg_size;
3467c478bd9Sstevel@tonic-gate
3477c478bd9Sstevel@tonic-gate if (compat20) {
3487c478bd9Sstevel@tonic-gate *n_bytes_ptr = packet_get_int();
3497c478bd9Sstevel@tonic-gate debug3("tty_parse_modes: SSH2 n_bytes %d", *n_bytes_ptr);
3507c478bd9Sstevel@tonic-gate if (*n_bytes_ptr == 0)
3517c478bd9Sstevel@tonic-gate return;
3527c478bd9Sstevel@tonic-gate get_arg = packet_get_int;
3537c478bd9Sstevel@tonic-gate arg_size = 4;
3547c478bd9Sstevel@tonic-gate } else {
3557c478bd9Sstevel@tonic-gate get_arg = packet_get_char;
3567c478bd9Sstevel@tonic-gate arg_size = 1;
3577c478bd9Sstevel@tonic-gate }
3587c478bd9Sstevel@tonic-gate
3597c478bd9Sstevel@tonic-gate /*
3607c478bd9Sstevel@tonic-gate * Get old attributes for the terminal. We will modify these
3617c478bd9Sstevel@tonic-gate * flags. I am hoping that if there are any machine-specific
3627c478bd9Sstevel@tonic-gate * modes, they will initially have reasonable values.
3637c478bd9Sstevel@tonic-gate */
3647c478bd9Sstevel@tonic-gate if (tcgetattr(fd, &tio) == -1) {
3657c478bd9Sstevel@tonic-gate log("tcgetattr: %.100s", strerror(errno));
3667c478bd9Sstevel@tonic-gate failure = -1;
3677c478bd9Sstevel@tonic-gate }
3687c478bd9Sstevel@tonic-gate
3697c478bd9Sstevel@tonic-gate for (;;) {
3707c478bd9Sstevel@tonic-gate n_bytes += 1;
3717c478bd9Sstevel@tonic-gate opcode = packet_get_char();
3727c478bd9Sstevel@tonic-gate switch (opcode) {
3737c478bd9Sstevel@tonic-gate case TTY_OP_END:
3747c478bd9Sstevel@tonic-gate goto set;
3757c478bd9Sstevel@tonic-gate
3767c478bd9Sstevel@tonic-gate /* XXX: future conflict possible */
3777c478bd9Sstevel@tonic-gate case TTY_OP_ISPEED_PROTO1:
3787c478bd9Sstevel@tonic-gate case TTY_OP_ISPEED_PROTO2:
3797c478bd9Sstevel@tonic-gate n_bytes += 4;
3807c478bd9Sstevel@tonic-gate baud = packet_get_int();
3817c478bd9Sstevel@tonic-gate debug3("tty_parse_modes: ispeed %d", baud);
3827c478bd9Sstevel@tonic-gate if (failure != -1 && cfsetispeed(&tio, baud_to_speed(baud)) == -1)
3837c478bd9Sstevel@tonic-gate error("cfsetispeed failed for %d", baud);
3847c478bd9Sstevel@tonic-gate break;
3857c478bd9Sstevel@tonic-gate
3867c478bd9Sstevel@tonic-gate /* XXX: future conflict possible */
3877c478bd9Sstevel@tonic-gate case TTY_OP_OSPEED_PROTO1:
3887c478bd9Sstevel@tonic-gate case TTY_OP_OSPEED_PROTO2:
3897c478bd9Sstevel@tonic-gate n_bytes += 4;
3907c478bd9Sstevel@tonic-gate baud = packet_get_int();
3917c478bd9Sstevel@tonic-gate debug3("tty_parse_modes: ospeed %d", baud);
3927c478bd9Sstevel@tonic-gate if (failure != -1 && cfsetospeed(&tio, baud_to_speed(baud)) == -1)
3937c478bd9Sstevel@tonic-gate error("cfsetospeed failed for %d", baud);
3947c478bd9Sstevel@tonic-gate break;
3957c478bd9Sstevel@tonic-gate
3967c478bd9Sstevel@tonic-gate #define TTYCHAR(NAME, OP) \
3977c478bd9Sstevel@tonic-gate case OP: \
3987c478bd9Sstevel@tonic-gate n_bytes += arg_size; \
3997c478bd9Sstevel@tonic-gate tio.c_cc[NAME] = get_arg(); \
4007c478bd9Sstevel@tonic-gate debug3("tty_parse_modes: %d %d", OP, tio.c_cc[NAME]); \
4017c478bd9Sstevel@tonic-gate break;
4027c478bd9Sstevel@tonic-gate #define TTYMODE(NAME, FIELD, OP) \
4037c478bd9Sstevel@tonic-gate case OP: \
4047c478bd9Sstevel@tonic-gate n_bytes += arg_size; \
4057c478bd9Sstevel@tonic-gate if ((arg = get_arg())) \
4067c478bd9Sstevel@tonic-gate tio.FIELD |= NAME; \
4077c478bd9Sstevel@tonic-gate else \
4087c478bd9Sstevel@tonic-gate tio.FIELD &= ~NAME; \
4097c478bd9Sstevel@tonic-gate debug3("tty_parse_modes: %d %d", OP, arg); \
4107c478bd9Sstevel@tonic-gate break;
4117c478bd9Sstevel@tonic-gate
4127c478bd9Sstevel@tonic-gate #include "ttymodes.h"
4137c478bd9Sstevel@tonic-gate
4147c478bd9Sstevel@tonic-gate #undef TTYCHAR
4157c478bd9Sstevel@tonic-gate #undef TTYMODE
4167c478bd9Sstevel@tonic-gate
4177c478bd9Sstevel@tonic-gate default:
4187c478bd9Sstevel@tonic-gate debug("Ignoring unsupported tty mode opcode %d (0x%x)",
4197c478bd9Sstevel@tonic-gate opcode, opcode);
4207c478bd9Sstevel@tonic-gate if (!compat20) {
4217c478bd9Sstevel@tonic-gate /*
4227c478bd9Sstevel@tonic-gate * SSH1:
4237c478bd9Sstevel@tonic-gate * Opcodes 1 to 127 are defined to have
4247c478bd9Sstevel@tonic-gate * a one-byte argument.
4257c478bd9Sstevel@tonic-gate * Opcodes 128 to 159 are defined to have
4267c478bd9Sstevel@tonic-gate * an integer argument.
4277c478bd9Sstevel@tonic-gate */
4287c478bd9Sstevel@tonic-gate if (opcode > 0 && opcode < 128) {
4297c478bd9Sstevel@tonic-gate n_bytes += 1;
4307c478bd9Sstevel@tonic-gate (void) packet_get_char();
4317c478bd9Sstevel@tonic-gate break;
4327c478bd9Sstevel@tonic-gate } else if (opcode >= 128 && opcode < 160) {
4337c478bd9Sstevel@tonic-gate n_bytes += 4;
4347c478bd9Sstevel@tonic-gate (void) packet_get_int();
4357c478bd9Sstevel@tonic-gate break;
4367c478bd9Sstevel@tonic-gate } else {
4377c478bd9Sstevel@tonic-gate /*
4387c478bd9Sstevel@tonic-gate * It is a truly undefined opcode (160 to 255).
4397c478bd9Sstevel@tonic-gate * We have no idea about its arguments. So we
4407c478bd9Sstevel@tonic-gate * must stop parsing. Note that some data may be
4417c478bd9Sstevel@tonic-gate * left in the packet; hopefully there is nothing
4427c478bd9Sstevel@tonic-gate * more coming after the mode data.
4437c478bd9Sstevel@tonic-gate */
4447c478bd9Sstevel@tonic-gate log("parse_tty_modes: unknown opcode %d", opcode);
4457c478bd9Sstevel@tonic-gate goto set;
4467c478bd9Sstevel@tonic-gate }
4477c478bd9Sstevel@tonic-gate } else {
4487c478bd9Sstevel@tonic-gate /*
4497c478bd9Sstevel@tonic-gate * SSH2:
4507c478bd9Sstevel@tonic-gate * Opcodes 1 to 159 are defined to have
4517c478bd9Sstevel@tonic-gate * a uint32 argument.
4527c478bd9Sstevel@tonic-gate * Opcodes 160 to 255 are undefined and
4537c478bd9Sstevel@tonic-gate * cause parsing to stop.
4547c478bd9Sstevel@tonic-gate */
4557c478bd9Sstevel@tonic-gate if (opcode > 0 && opcode < 160) {
4567c478bd9Sstevel@tonic-gate n_bytes += 4;
4577c478bd9Sstevel@tonic-gate (void) packet_get_int();
4587c478bd9Sstevel@tonic-gate break;
4597c478bd9Sstevel@tonic-gate } else {
4607c478bd9Sstevel@tonic-gate log("parse_tty_modes: unknown opcode %d", opcode);
4617c478bd9Sstevel@tonic-gate goto set;
4627c478bd9Sstevel@tonic-gate }
4637c478bd9Sstevel@tonic-gate }
4647c478bd9Sstevel@tonic-gate }
4657c478bd9Sstevel@tonic-gate }
4667c478bd9Sstevel@tonic-gate
4677c478bd9Sstevel@tonic-gate set:
4687c478bd9Sstevel@tonic-gate if (*n_bytes_ptr != n_bytes) {
4697c478bd9Sstevel@tonic-gate *n_bytes_ptr = n_bytes;
4707c478bd9Sstevel@tonic-gate log("parse_tty_modes: n_bytes_ptr != n_bytes: %d %d",
4717c478bd9Sstevel@tonic-gate *n_bytes_ptr, n_bytes);
4727c478bd9Sstevel@tonic-gate return; /* Don't process bytes passed */
4737c478bd9Sstevel@tonic-gate }
4747c478bd9Sstevel@tonic-gate if (failure == -1)
4757c478bd9Sstevel@tonic-gate return; /* Packet parsed ok but tcgetattr() failed */
4767c478bd9Sstevel@tonic-gate
4777c478bd9Sstevel@tonic-gate /* Set the new modes for the terminal. */
4787c478bd9Sstevel@tonic-gate if (tcsetattr(fd, TCSANOW, &tio) == -1)
4797c478bd9Sstevel@tonic-gate log("Setting tty modes failed: %.100s", strerror(errno));
4807c478bd9Sstevel@tonic-gate }
481