1*19261079SEd Maste /* $OpenBSD: ttymodes.c,v 1.36 2021/01/27 09:26:54 djm 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"
58190cef3dSDag-Erling Smørgrav #include "sshbuf.h"
59190cef3dSDag-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
speed_to_baud(speed_t speed)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
baud_to_speed(int baud)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
special_char_encode(cc_t c)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
special_char_decode(u_int c)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
ssh_tty_make_modes(struct ssh * ssh,int fd,struct termios * tiop)279190cef3dSDag-Erling Smørgrav ssh_tty_make_modes(struct ssh *ssh, int fd, struct termios *tiop)
280511b41d2SMark Murray {
281511b41d2SMark Murray struct termios tio;
282190cef3dSDag-Erling Smørgrav struct sshbuf *buf;
283190cef3dSDag-Erling Smørgrav int r, ibaud, obaud;
284511b41d2SMark Murray
285190cef3dSDag-Erling Smørgrav if ((buf = sshbuf_new()) == NULL)
286*19261079SEd Maste fatal_f("sshbuf_new failed");
2871e8db6e2SBrian Feldman
2881e8db6e2SBrian Feldman if (tiop == NULL) {
289d4af9e69SDag-Erling Smørgrav if (fd == -1) {
290*19261079SEd Maste debug_f("no fd or tio");
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. */
301190cef3dSDag-Erling Smørgrav obaud = speed_to_baud(cfgetospeed(&tio));
302190cef3dSDag-Erling Smørgrav ibaud = speed_to_baud(cfgetispeed(&tio));
303190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_u8(buf, TTY_OP_OSPEED)) != 0 ||
304190cef3dSDag-Erling Smørgrav (r = sshbuf_put_u32(buf, obaud)) != 0 ||
305190cef3dSDag-Erling Smørgrav (r = sshbuf_put_u8(buf, TTY_OP_ISPEED)) != 0 ||
306190cef3dSDag-Erling Smørgrav (r = sshbuf_put_u32(buf, ibaud)) != 0)
307*19261079SEd Maste fatal_fr(r, "compose");
308511b41d2SMark Murray
309511b41d2SMark Murray /* Store values of mode flags. */
310511b41d2SMark Murray #define TTYCHAR(NAME, OP) \
311190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_u8(buf, OP)) != 0 || \
312190cef3dSDag-Erling Smørgrav (r = sshbuf_put_u32(buf, \
313190cef3dSDag-Erling Smørgrav special_char_encode(tio.c_cc[NAME]))) != 0) \
314*19261079SEd Maste fatal_fr(r, "compose %s", #NAME);
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) \
319*19261079SEd Maste if (OP == SSH_TTYMODE_IUTF8 && (ssh->compat & SSH_BUG_UTF8TTYMODE)) { \
320*19261079SEd Maste debug3_f("SSH_BUG_UTF8TTYMODE"); \
321190cef3dSDag-Erling Smørgrav } else if ((r = sshbuf_put_u8(buf, OP)) != 0 || \
322190cef3dSDag-Erling Smørgrav (r = sshbuf_put_u32(buf, ((tio.FIELD & NAME) != 0))) != 0) \
323*19261079SEd Maste fatal_fr(r, "compose %s", #NAME);
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. */
332190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put_u8(buf, TTY_OP_END)) != 0 ||
333190cef3dSDag-Erling Smørgrav (r = sshpkt_put_stringb(ssh, buf)) != 0)
334*19261079SEd Maste fatal_fr(r, "compose end");
335190cef3dSDag-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
ssh_tty_parse_modes(struct ssh * ssh,int fd)343190cef3dSDag-Erling Smørgrav ssh_tty_parse_modes(struct ssh *ssh, int fd)
344511b41d2SMark Murray {
345511b41d2SMark Murray struct termios tio;
346190cef3dSDag-Erling Smørgrav struct sshbuf *buf;
347190cef3dSDag-Erling Smørgrav const u_char *data;
348190cef3dSDag-Erling Smørgrav u_char opcode;
349190cef3dSDag-Erling Smørgrav u_int baud, u;
350190cef3dSDag-Erling Smørgrav int r, failure = 0;
351190cef3dSDag-Erling Smørgrav size_t len;
3521e8db6e2SBrian Feldman
353190cef3dSDag-Erling Smørgrav if ((r = sshpkt_get_string_direct(ssh, &data, &len)) != 0)
354*19261079SEd Maste fatal_fr(r, "parse");
355190cef3dSDag-Erling Smørgrav if (len == 0)
3561e8db6e2SBrian Feldman return;
357190cef3dSDag-Erling Smørgrav if ((buf = sshbuf_from(data, len)) == NULL) {
358*19261079SEd Maste error_f("sshbuf_from failed");
359190cef3dSDag-Erling Smørgrav return;
360190cef3dSDag-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
372190cef3dSDag-Erling Smørgrav while (sshbuf_len(buf) > 0) {
373190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_u8(buf, &opcode)) != 0)
374*19261079SEd Maste fatal_fr(r, "parse opcode");
375511b41d2SMark Murray switch (opcode) {
376511b41d2SMark Murray case TTY_OP_END:
377511b41d2SMark Murray goto set;
378511b41d2SMark Murray
3794f52dfbbSDag-Erling Smørgrav case TTY_OP_ISPEED:
380190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_u32(buf, &baud)) != 0)
381*19261079SEd Maste fatal_fr(r, "parse ispeed");
382761efaa7SDag-Erling Smørgrav if (failure != -1 &&
383761efaa7SDag-Erling Smørgrav cfsetispeed(&tio, baud_to_speed(baud)) == -1)
384511b41d2SMark Murray error("cfsetispeed failed for %d", baud);
385511b41d2SMark Murray break;
386511b41d2SMark Murray
3874f52dfbbSDag-Erling Smørgrav case TTY_OP_OSPEED:
388190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_u32(buf, &baud)) != 0)
389*19261079SEd Maste fatal_fr(r, "parse ospeed");
390761efaa7SDag-Erling Smørgrav if (failure != -1 &&
391761efaa7SDag-Erling Smørgrav cfsetospeed(&tio, baud_to_speed(baud)) == -1)
392511b41d2SMark Murray error("cfsetospeed failed for %d", baud);
393511b41d2SMark Murray break;
394511b41d2SMark Murray
395511b41d2SMark Murray #define TTYCHAR(NAME, OP) \
396511b41d2SMark Murray case OP: \
397190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_u32(buf, &u)) != 0) \
398*19261079SEd Maste fatal_fr(r, "parse %s", #NAME); \
399190cef3dSDag-Erling Smørgrav tio.c_cc[NAME] = special_char_decode(u); \
400511b41d2SMark Murray break;
401511b41d2SMark Murray #define TTYMODE(NAME, FIELD, OP) \
402511b41d2SMark Murray case OP: \
403190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_u32(buf, &u)) != 0) \
404*19261079SEd Maste fatal_fr(r, "parse %s", #NAME); \
405190cef3dSDag-Erling Smørgrav if (u) \
406511b41d2SMark Murray tio.FIELD |= NAME; \
407511b41d2SMark Murray else \
408511b41d2SMark Murray tio.FIELD &= ~NAME; \
409511b41d2SMark Murray break;
410511b41d2SMark Murray
411511b41d2SMark Murray #include "ttymodes.h"
412511b41d2SMark Murray
413511b41d2SMark Murray #undef TTYCHAR
414511b41d2SMark Murray #undef TTYMODE
415511b41d2SMark Murray
416511b41d2SMark Murray default:
417511b41d2SMark Murray debug("Ignoring unsupported tty mode opcode %d (0x%x)",
418511b41d2SMark Murray opcode, opcode);
4191e8db6e2SBrian Feldman /*
4201e8db6e2SBrian Feldman * SSH2:
4214f52dfbbSDag-Erling Smørgrav * Opcodes 1 to 159 are defined to have a uint32
4224f52dfbbSDag-Erling Smørgrav * argument.
4234f52dfbbSDag-Erling Smørgrav * Opcodes 160 to 255 are undefined and cause parsing
4244f52dfbbSDag-Erling Smørgrav * to stop.
4251e8db6e2SBrian Feldman */
4261e8db6e2SBrian Feldman if (opcode > 0 && opcode < 160) {
427190cef3dSDag-Erling Smørgrav if ((r = sshbuf_get_u32(buf, NULL)) != 0)
428*19261079SEd Maste fatal_fr(r, "parse arg");
4291e8db6e2SBrian Feldman break;
4301e8db6e2SBrian Feldman } else {
431*19261079SEd Maste logit_f("unknown opcode %d", opcode);
4321e8db6e2SBrian Feldman goto set;
4331e8db6e2SBrian Feldman }
4341e8db6e2SBrian Feldman }
4351e8db6e2SBrian Feldman }
436511b41d2SMark Murray
437511b41d2SMark Murray set:
438190cef3dSDag-Erling Smørgrav len = sshbuf_len(buf);
439190cef3dSDag-Erling Smørgrav sshbuf_free(buf);
440190cef3dSDag-Erling Smørgrav if (len > 0) {
441*19261079SEd Maste logit_f("%zu bytes left", len);
442511b41d2SMark Murray return; /* Don't process bytes passed */
443511b41d2SMark Murray }
444511b41d2SMark Murray if (failure == -1)
4451e8db6e2SBrian Feldman return; /* Packet parsed ok but tcgetattr() failed */
446511b41d2SMark Murray
447511b41d2SMark Murray /* Set the new modes for the terminal. */
4481e8db6e2SBrian Feldman if (tcsetattr(fd, TCSANOW, &tio) == -1)
449d95e11bfSDag-Erling Smørgrav logit("Setting tty modes failed: %.100s", strerror(errno));
450511b41d2SMark Murray }
451