diff options
Diffstat (limited to 'nchan.c')
-rw-r--r-- | nchan.c | 369 |
1 files changed, 126 insertions, 243 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: nchan.c,v 1.63 2010/01/26 01:28:35 djm Exp $ */ | 1 | /* $OpenBSD: nchan.c,v 1.67 2017/09/12 06:35:32 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -33,9 +33,9 @@ | |||
33 | #include <stdarg.h> | 33 | #include <stdarg.h> |
34 | 34 | ||
35 | #include "openbsd-compat/sys-queue.h" | 35 | #include "openbsd-compat/sys-queue.h" |
36 | #include "ssh1.h" | ||
37 | #include "ssh2.h" | 36 | #include "ssh2.h" |
38 | #include "buffer.h" | 37 | #include "sshbuf.h" |
38 | #include "ssherr.h" | ||
39 | #include "packet.h" | 39 | #include "packet.h" |
40 | #include "channels.h" | 40 | #include "channels.h" |
41 | #include "compat.h" | 41 | #include "compat.h" |
@@ -74,18 +74,15 @@ | |||
74 | /* | 74 | /* |
75 | * ACTIONS: should never update the channel states | 75 | * ACTIONS: should never update the channel states |
76 | */ | 76 | */ |
77 | static void chan_send_ieof1(Channel *); | 77 | static void chan_send_eof2(struct ssh *, Channel *); |
78 | static void chan_send_oclose1(Channel *); | 78 | static void chan_send_eow2(struct ssh *, Channel *); |
79 | static void chan_send_close2(Channel *); | ||
80 | static void chan_send_eof2(Channel *); | ||
81 | static void chan_send_eow2(Channel *); | ||
82 | 79 | ||
83 | /* helper */ | 80 | /* helper */ |
84 | static void chan_shutdown_write(Channel *); | 81 | static void chan_shutdown_write(struct ssh *, Channel *); |
85 | static void chan_shutdown_read(Channel *); | 82 | static void chan_shutdown_read(struct ssh *, Channel *); |
86 | 83 | ||
87 | static char *ostates[] = { "open", "drain", "wait_ieof", "closed" }; | 84 | static const char *ostates[] = { "open", "drain", "wait_ieof", "closed" }; |
88 | static char *istates[] = { "open", "drain", "wait_oclose", "closed" }; | 85 | static const char *istates[] = { "open", "drain", "wait_oclose", "closed" }; |
89 | 86 | ||
90 | static void | 87 | static void |
91 | chan_set_istate(Channel *c, u_int next) | 88 | chan_set_istate(Channel *c, u_int next) |
@@ -96,6 +93,7 @@ chan_set_istate(Channel *c, u_int next) | |||
96 | istates[next]); | 93 | istates[next]); |
97 | c->istate = next; | 94 | c->istate = next; |
98 | } | 95 | } |
96 | |||
99 | static void | 97 | static void |
100 | chan_set_ostate(Channel *c, u_int next) | 98 | chan_set_ostate(Channel *c, u_int next) |
101 | { | 99 | { |
@@ -106,41 +104,13 @@ chan_set_ostate(Channel *c, u_int next) | |||
106 | c->ostate = next; | 104 | c->ostate = next; |
107 | } | 105 | } |
108 | 106 | ||
109 | /* | ||
110 | * SSH1 specific implementation of event functions | ||
111 | */ | ||
112 | |||
113 | static void | ||
114 | chan_rcvd_oclose1(Channel *c) | ||
115 | { | ||
116 | debug2("channel %d: rcvd oclose", c->self); | ||
117 | switch (c->istate) { | ||
118 | case CHAN_INPUT_WAIT_OCLOSE: | ||
119 | chan_set_istate(c, CHAN_INPUT_CLOSED); | ||
120 | break; | ||
121 | case CHAN_INPUT_OPEN: | ||
122 | chan_shutdown_read(c); | ||
123 | chan_send_ieof1(c); | ||
124 | chan_set_istate(c, CHAN_INPUT_CLOSED); | ||
125 | break; | ||
126 | case CHAN_INPUT_WAIT_DRAIN: | ||
127 | /* both local read_failed and remote write_failed */ | ||
128 | chan_send_ieof1(c); | ||
129 | chan_set_istate(c, CHAN_INPUT_CLOSED); | ||
130 | break; | ||
131 | default: | ||
132 | error("channel %d: protocol error: rcvd_oclose for istate %d", | ||
133 | c->self, c->istate); | ||
134 | return; | ||
135 | } | ||
136 | } | ||
137 | void | 107 | void |
138 | chan_read_failed(Channel *c) | 108 | chan_read_failed(struct ssh *ssh, Channel *c) |
139 | { | 109 | { |
140 | debug2("channel %d: read failed", c->self); | 110 | debug2("channel %d: read failed", c->self); |
141 | switch (c->istate) { | 111 | switch (c->istate) { |
142 | case CHAN_INPUT_OPEN: | 112 | case CHAN_INPUT_OPEN: |
143 | chan_shutdown_read(c); | 113 | chan_shutdown_read(ssh, c); |
144 | chan_set_istate(c, CHAN_INPUT_WAIT_DRAIN); | 114 | chan_set_istate(c, CHAN_INPUT_WAIT_DRAIN); |
145 | break; | 115 | break; |
146 | default: | 116 | default: |
@@ -149,25 +119,21 @@ chan_read_failed(Channel *c) | |||
149 | break; | 119 | break; |
150 | } | 120 | } |
151 | } | 121 | } |
122 | |||
152 | void | 123 | void |
153 | chan_ibuf_empty(Channel *c) | 124 | chan_ibuf_empty(struct ssh *ssh, Channel *c) |
154 | { | 125 | { |
155 | debug2("channel %d: ibuf empty", c->self); | 126 | debug2("channel %d: ibuf empty", c->self); |
156 | if (buffer_len(&c->input)) { | 127 | if (sshbuf_len(c->input)) { |
157 | error("channel %d: chan_ibuf_empty for non empty buffer", | 128 | error("channel %d: chan_ibuf_empty for non empty buffer", |
158 | c->self); | 129 | c->self); |
159 | return; | 130 | return; |
160 | } | 131 | } |
161 | switch (c->istate) { | 132 | switch (c->istate) { |
162 | case CHAN_INPUT_WAIT_DRAIN: | 133 | case CHAN_INPUT_WAIT_DRAIN: |
163 | if (compat20) { | 134 | if (!(c->flags & (CHAN_CLOSE_SENT|CHAN_LOCAL))) |
164 | if (!(c->flags & (CHAN_CLOSE_SENT|CHAN_LOCAL))) | 135 | chan_send_eof2(ssh, c); |
165 | chan_send_eof2(c); | 136 | chan_set_istate(c, CHAN_INPUT_CLOSED); |
166 | chan_set_istate(c, CHAN_INPUT_CLOSED); | ||
167 | } else { | ||
168 | chan_send_ieof1(c); | ||
169 | chan_set_istate(c, CHAN_INPUT_WAIT_OCLOSE); | ||
170 | } | ||
171 | break; | 137 | break; |
172 | default: | 138 | default: |
173 | error("channel %d: chan_ibuf_empty for istate %d", | 139 | error("channel %d: chan_ibuf_empty for istate %d", |
@@ -175,58 +141,19 @@ chan_ibuf_empty(Channel *c) | |||
175 | break; | 141 | break; |
176 | } | 142 | } |
177 | } | 143 | } |
178 | static void | 144 | |
179 | chan_rcvd_ieof1(Channel *c) | ||
180 | { | ||
181 | debug2("channel %d: rcvd ieof", c->self); | ||
182 | switch (c->ostate) { | ||
183 | case CHAN_OUTPUT_OPEN: | ||
184 | chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN); | ||
185 | break; | ||
186 | case CHAN_OUTPUT_WAIT_IEOF: | ||
187 | chan_set_ostate(c, CHAN_OUTPUT_CLOSED); | ||
188 | break; | ||
189 | default: | ||
190 | error("channel %d: protocol error: rcvd_ieof for ostate %d", | ||
191 | c->self, c->ostate); | ||
192 | break; | ||
193 | } | ||
194 | } | ||
195 | static void | ||
196 | chan_write_failed1(Channel *c) | ||
197 | { | ||
198 | debug2("channel %d: write failed", c->self); | ||
199 | switch (c->ostate) { | ||
200 | case CHAN_OUTPUT_OPEN: | ||
201 | chan_shutdown_write(c); | ||
202 | chan_send_oclose1(c); | ||
203 | chan_set_ostate(c, CHAN_OUTPUT_WAIT_IEOF); | ||
204 | break; | ||
205 | case CHAN_OUTPUT_WAIT_DRAIN: | ||
206 | chan_shutdown_write(c); | ||
207 | chan_send_oclose1(c); | ||
208 | chan_set_ostate(c, CHAN_OUTPUT_CLOSED); | ||
209 | break; | ||
210 | default: | ||
211 | error("channel %d: chan_write_failed for ostate %d", | ||
212 | c->self, c->ostate); | ||
213 | break; | ||
214 | } | ||
215 | } | ||
216 | void | 145 | void |
217 | chan_obuf_empty(Channel *c) | 146 | chan_obuf_empty(struct ssh *ssh, Channel *c) |
218 | { | 147 | { |
219 | debug2("channel %d: obuf empty", c->self); | 148 | debug2("channel %d: obuf empty", c->self); |
220 | if (buffer_len(&c->output)) { | 149 | if (sshbuf_len(c->output)) { |
221 | error("channel %d: chan_obuf_empty for non empty buffer", | 150 | error("channel %d: chan_obuf_empty for non empty buffer", |
222 | c->self); | 151 | c->self); |
223 | return; | 152 | return; |
224 | } | 153 | } |
225 | switch (c->ostate) { | 154 | switch (c->ostate) { |
226 | case CHAN_OUTPUT_WAIT_DRAIN: | 155 | case CHAN_OUTPUT_WAIT_DRAIN: |
227 | chan_shutdown_write(c); | 156 | chan_shutdown_write(ssh, c); |
228 | if (!compat20) | ||
229 | chan_send_oclose1(c); | ||
230 | chan_set_ostate(c, CHAN_OUTPUT_CLOSED); | 157 | chan_set_ostate(c, CHAN_OUTPUT_CLOSED); |
231 | break; | 158 | break; |
232 | default: | 159 | default: |
@@ -235,47 +162,107 @@ chan_obuf_empty(Channel *c) | |||
235 | break; | 162 | break; |
236 | } | 163 | } |
237 | } | 164 | } |
238 | static void | 165 | |
239 | chan_send_ieof1(Channel *c) | 166 | void |
167 | chan_rcvd_eow(struct ssh *ssh, Channel *c) | ||
240 | { | 168 | { |
241 | debug2("channel %d: send ieof", c->self); | 169 | debug2("channel %d: rcvd eow", c->self); |
242 | switch (c->istate) { | 170 | switch (c->istate) { |
243 | case CHAN_INPUT_OPEN: | 171 | case CHAN_INPUT_OPEN: |
172 | chan_shutdown_read(ssh, c); | ||
173 | chan_set_istate(c, CHAN_INPUT_CLOSED); | ||
174 | break; | ||
175 | } | ||
176 | } | ||
177 | |||
178 | static void | ||
179 | chan_send_eof2(struct ssh *ssh, Channel *c) | ||
180 | { | ||
181 | int r; | ||
182 | |||
183 | debug2("channel %d: send eof", c->self); | ||
184 | switch (c->istate) { | ||
244 | case CHAN_INPUT_WAIT_DRAIN: | 185 | case CHAN_INPUT_WAIT_DRAIN: |
245 | packet_start(SSH_MSG_CHANNEL_INPUT_EOF); | 186 | if (!c->have_remote_id) |
246 | packet_put_int(c->remote_id); | 187 | fatal("%s: channel %d: no remote_id", |
247 | packet_send(); | 188 | __func__, c->self); |
189 | if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_EOF)) != 0 || | ||
190 | (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || | ||
191 | (r = sshpkt_send(ssh)) != 0) | ||
192 | fatal("%s: send CHANNEL_EOF: %s", __func__, ssh_err(r)); | ||
193 | c->flags |= CHAN_EOF_SENT; | ||
248 | break; | 194 | break; |
249 | default: | 195 | default: |
250 | error("channel %d: cannot send ieof for istate %d", | 196 | error("channel %d: cannot send eof for istate %d", |
251 | c->self, c->istate); | 197 | c->self, c->istate); |
252 | break; | 198 | break; |
253 | } | 199 | } |
254 | } | 200 | } |
201 | |||
255 | static void | 202 | static void |
256 | chan_send_oclose1(Channel *c) | 203 | chan_send_close2(struct ssh *ssh, Channel *c) |
257 | { | 204 | { |
258 | debug2("channel %d: send oclose", c->self); | 205 | int r; |
259 | switch (c->ostate) { | 206 | |
260 | case CHAN_OUTPUT_OPEN: | 207 | debug2("channel %d: send close", c->self); |
261 | case CHAN_OUTPUT_WAIT_DRAIN: | 208 | if (c->ostate != CHAN_OUTPUT_CLOSED || |
262 | buffer_clear(&c->output); | 209 | c->istate != CHAN_INPUT_CLOSED) { |
263 | packet_start(SSH_MSG_CHANNEL_OUTPUT_CLOSE); | 210 | error("channel %d: cannot send close for istate/ostate %d/%d", |
264 | packet_put_int(c->remote_id); | 211 | c->self, c->istate, c->ostate); |
265 | packet_send(); | 212 | } else if (c->flags & CHAN_CLOSE_SENT) { |
266 | break; | 213 | error("channel %d: already sent close", c->self); |
267 | default: | 214 | } else { |
268 | error("channel %d: cannot send oclose for ostate %d", | 215 | if (!c->have_remote_id) |
269 | c->self, c->ostate); | 216 | fatal("%s: channel %d: no remote_id", |
270 | break; | 217 | __func__, c->self); |
218 | if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_CLOSE)) != 0 || | ||
219 | (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || | ||
220 | (r = sshpkt_send(ssh)) != 0) | ||
221 | fatal("%s: send CHANNEL_EOF: %s", __func__, ssh_err(r)); | ||
222 | c->flags |= CHAN_CLOSE_SENT; | ||
271 | } | 223 | } |
272 | } | 224 | } |
273 | 225 | ||
274 | /* | ||
275 | * the same for SSH2 | ||
276 | */ | ||
277 | static void | 226 | static void |
278 | chan_rcvd_close2(Channel *c) | 227 | chan_send_eow2(struct ssh *ssh, Channel *c) |
228 | { | ||
229 | int r; | ||
230 | |||
231 | debug2("channel %d: send eow", c->self); | ||
232 | if (c->ostate == CHAN_OUTPUT_CLOSED) { | ||
233 | error("channel %d: must not sent eow on closed output", | ||
234 | c->self); | ||
235 | return; | ||
236 | } | ||
237 | if (!(datafellows & SSH_NEW_OPENSSH)) | ||
238 | return; | ||
239 | if (!c->have_remote_id) | ||
240 | fatal("%s: channel %d: no remote_id", __func__, c->self); | ||
241 | if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_REQUEST)) != 0 || | ||
242 | (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || | ||
243 | (r = sshpkt_put_cstring(ssh, "eow@openssh.com")) != 0 || | ||
244 | (r = sshpkt_put_u8(ssh, 0)) != 0 || | ||
245 | (r = sshpkt_send(ssh)) != 0) | ||
246 | fatal("%s: send CHANNEL_EOF: %s", __func__, ssh_err(r)); | ||
247 | } | ||
248 | |||
249 | /* shared */ | ||
250 | |||
251 | void | ||
252 | chan_rcvd_ieof(struct ssh *ssh, Channel *c) | ||
253 | { | ||
254 | debug2("channel %d: rcvd eof", c->self); | ||
255 | c->flags |= CHAN_EOF_RCVD; | ||
256 | if (c->ostate == CHAN_OUTPUT_OPEN) | ||
257 | chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN); | ||
258 | if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN && | ||
259 | sshbuf_len(c->output) == 0 && | ||
260 | !CHANNEL_EFD_OUTPUT_ACTIVE(c)) | ||
261 | chan_obuf_empty(ssh, c); | ||
262 | } | ||
263 | |||
264 | void | ||
265 | chan_rcvd_oclose(struct ssh *ssh, Channel *c) | ||
279 | { | 266 | { |
280 | debug2("channel %d: rcvd close", c->self); | 267 | debug2("channel %d: rcvd close", c->self); |
281 | if (!(c->flags & CHAN_LOCAL)) { | 268 | if (!(c->flags & CHAN_LOCAL)) { |
@@ -301,46 +288,27 @@ chan_rcvd_close2(Channel *c) | |||
301 | } | 288 | } |
302 | switch (c->istate) { | 289 | switch (c->istate) { |
303 | case CHAN_INPUT_OPEN: | 290 | case CHAN_INPUT_OPEN: |
304 | chan_shutdown_read(c); | 291 | chan_shutdown_read(ssh, c); |
305 | chan_set_istate(c, CHAN_INPUT_CLOSED); | 292 | chan_set_istate(c, CHAN_INPUT_CLOSED); |
306 | break; | 293 | break; |
307 | case CHAN_INPUT_WAIT_DRAIN: | 294 | case CHAN_INPUT_WAIT_DRAIN: |
308 | if (!(c->flags & CHAN_LOCAL)) | 295 | if (!(c->flags & CHAN_LOCAL)) |
309 | chan_send_eof2(c); | 296 | chan_send_eof2(ssh, c); |
310 | chan_set_istate(c, CHAN_INPUT_CLOSED); | 297 | chan_set_istate(c, CHAN_INPUT_CLOSED); |
311 | break; | 298 | break; |
312 | } | 299 | } |
313 | } | 300 | } |
314 | 301 | ||
315 | void | 302 | void |
316 | chan_rcvd_eow(Channel *c) | 303 | chan_write_failed(struct ssh *ssh, Channel *c) |
317 | { | ||
318 | debug2("channel %d: rcvd eow", c->self); | ||
319 | switch (c->istate) { | ||
320 | case CHAN_INPUT_OPEN: | ||
321 | chan_shutdown_read(c); | ||
322 | chan_set_istate(c, CHAN_INPUT_CLOSED); | ||
323 | break; | ||
324 | } | ||
325 | } | ||
326 | static void | ||
327 | chan_rcvd_eof2(Channel *c) | ||
328 | { | ||
329 | debug2("channel %d: rcvd eof", c->self); | ||
330 | c->flags |= CHAN_EOF_RCVD; | ||
331 | if (c->ostate == CHAN_OUTPUT_OPEN) | ||
332 | chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN); | ||
333 | } | ||
334 | static void | ||
335 | chan_write_failed2(Channel *c) | ||
336 | { | 304 | { |
337 | debug2("channel %d: write failed", c->self); | 305 | debug2("channel %d: write failed", c->self); |
338 | switch (c->ostate) { | 306 | switch (c->ostate) { |
339 | case CHAN_OUTPUT_OPEN: | 307 | case CHAN_OUTPUT_OPEN: |
340 | case CHAN_OUTPUT_WAIT_DRAIN: | 308 | case CHAN_OUTPUT_WAIT_DRAIN: |
341 | chan_shutdown_write(c); | 309 | chan_shutdown_write(ssh, c); |
342 | if (strcmp(c->ctype, "session") == 0) | 310 | if (strcmp(c->ctype, "session") == 0) |
343 | chan_send_eow2(c); | 311 | chan_send_eow2(ssh, c); |
344 | chan_set_ostate(c, CHAN_OUTPUT_CLOSED); | 312 | chan_set_ostate(c, CHAN_OUTPUT_CLOSED); |
345 | break; | 313 | break; |
346 | default: | 314 | default: |
@@ -349,97 +317,15 @@ chan_write_failed2(Channel *c) | |||
349 | break; | 317 | break; |
350 | } | 318 | } |
351 | } | 319 | } |
352 | static void | ||
353 | chan_send_eof2(Channel *c) | ||
354 | { | ||
355 | debug2("channel %d: send eof", c->self); | ||
356 | switch (c->istate) { | ||
357 | case CHAN_INPUT_WAIT_DRAIN: | ||
358 | packet_start(SSH2_MSG_CHANNEL_EOF); | ||
359 | packet_put_int(c->remote_id); | ||
360 | packet_send(); | ||
361 | c->flags |= CHAN_EOF_SENT; | ||
362 | break; | ||
363 | default: | ||
364 | error("channel %d: cannot send eof for istate %d", | ||
365 | c->self, c->istate); | ||
366 | break; | ||
367 | } | ||
368 | } | ||
369 | static void | ||
370 | chan_send_close2(Channel *c) | ||
371 | { | ||
372 | debug2("channel %d: send close", c->self); | ||
373 | if (c->ostate != CHAN_OUTPUT_CLOSED || | ||
374 | c->istate != CHAN_INPUT_CLOSED) { | ||
375 | error("channel %d: cannot send close for istate/ostate %d/%d", | ||
376 | c->self, c->istate, c->ostate); | ||
377 | } else if (c->flags & CHAN_CLOSE_SENT) { | ||
378 | error("channel %d: already sent close", c->self); | ||
379 | } else { | ||
380 | packet_start(SSH2_MSG_CHANNEL_CLOSE); | ||
381 | packet_put_int(c->remote_id); | ||
382 | packet_send(); | ||
383 | c->flags |= CHAN_CLOSE_SENT; | ||
384 | } | ||
385 | } | ||
386 | static void | ||
387 | chan_send_eow2(Channel *c) | ||
388 | { | ||
389 | debug2("channel %d: send eow", c->self); | ||
390 | if (c->ostate == CHAN_OUTPUT_CLOSED) { | ||
391 | error("channel %d: must not sent eow on closed output", | ||
392 | c->self); | ||
393 | return; | ||
394 | } | ||
395 | if (!(datafellows & SSH_NEW_OPENSSH)) | ||
396 | return; | ||
397 | packet_start(SSH2_MSG_CHANNEL_REQUEST); | ||
398 | packet_put_int(c->remote_id); | ||
399 | packet_put_cstring("eow@openssh.com"); | ||
400 | packet_put_char(0); | ||
401 | packet_send(); | ||
402 | } | ||
403 | |||
404 | /* shared */ | ||
405 | 320 | ||
406 | void | 321 | void |
407 | chan_rcvd_ieof(Channel *c) | 322 | chan_mark_dead(struct ssh *ssh, Channel *c) |
408 | { | ||
409 | if (compat20) | ||
410 | chan_rcvd_eof2(c); | ||
411 | else | ||
412 | chan_rcvd_ieof1(c); | ||
413 | if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN && | ||
414 | buffer_len(&c->output) == 0 && | ||
415 | !CHANNEL_EFD_OUTPUT_ACTIVE(c)) | ||
416 | chan_obuf_empty(c); | ||
417 | } | ||
418 | void | ||
419 | chan_rcvd_oclose(Channel *c) | ||
420 | { | ||
421 | if (compat20) | ||
422 | chan_rcvd_close2(c); | ||
423 | else | ||
424 | chan_rcvd_oclose1(c); | ||
425 | } | ||
426 | void | ||
427 | chan_write_failed(Channel *c) | ||
428 | { | ||
429 | if (compat20) | ||
430 | chan_write_failed2(c); | ||
431 | else | ||
432 | chan_write_failed1(c); | ||
433 | } | ||
434 | |||
435 | void | ||
436 | chan_mark_dead(Channel *c) | ||
437 | { | 323 | { |
438 | c->type = SSH_CHANNEL_ZOMBIE; | 324 | c->type = SSH_CHANNEL_ZOMBIE; |
439 | } | 325 | } |
440 | 326 | ||
441 | int | 327 | int |
442 | chan_is_dead(Channel *c, int do_send) | 328 | chan_is_dead(struct ssh *ssh, Channel *c, int do_send) |
443 | { | 329 | { |
444 | if (c->type == SSH_CHANNEL_ZOMBIE) { | 330 | if (c->type == SSH_CHANNEL_ZOMBIE) { |
445 | debug2("channel %d: zombie", c->self); | 331 | debug2("channel %d: zombie", c->self); |
@@ -447,16 +333,12 @@ chan_is_dead(Channel *c, int do_send) | |||
447 | } | 333 | } |
448 | if (c->istate != CHAN_INPUT_CLOSED || c->ostate != CHAN_OUTPUT_CLOSED) | 334 | if (c->istate != CHAN_INPUT_CLOSED || c->ostate != CHAN_OUTPUT_CLOSED) |
449 | return 0; | 335 | return 0; |
450 | if (!compat20) { | ||
451 | debug2("channel %d: is dead", c->self); | ||
452 | return 1; | ||
453 | } | ||
454 | if ((datafellows & SSH_BUG_EXTEOF) && | 336 | if ((datafellows & SSH_BUG_EXTEOF) && |
455 | c->extended_usage == CHAN_EXTENDED_WRITE && | 337 | c->extended_usage == CHAN_EXTENDED_WRITE && |
456 | c->efd != -1 && | 338 | c->efd != -1 && |
457 | buffer_len(&c->extended) > 0) { | 339 | sshbuf_len(c->extended) > 0) { |
458 | debug2("channel %d: active efd: %d len %d", | 340 | debug2("channel %d: active efd: %d len %zu", |
459 | c->self, c->efd, buffer_len(&c->extended)); | 341 | c->self, c->efd, sshbuf_len(c->extended)); |
460 | return 0; | 342 | return 0; |
461 | } | 343 | } |
462 | if (c->flags & CHAN_LOCAL) { | 344 | if (c->flags & CHAN_LOCAL) { |
@@ -465,7 +347,7 @@ chan_is_dead(Channel *c, int do_send) | |||
465 | } | 347 | } |
466 | if (!(c->flags & CHAN_CLOSE_SENT)) { | 348 | if (!(c->flags & CHAN_CLOSE_SENT)) { |
467 | if (do_send) { | 349 | if (do_send) { |
468 | chan_send_close2(c); | 350 | chan_send_close2(ssh, c); |
469 | } else { | 351 | } else { |
470 | /* channel would be dead if we sent a close */ | 352 | /* channel would be dead if we sent a close */ |
471 | if (c->flags & CHAN_CLOSE_RCVD) { | 353 | if (c->flags & CHAN_CLOSE_RCVD) { |
@@ -485,10 +367,10 @@ chan_is_dead(Channel *c, int do_send) | |||
485 | 367 | ||
486 | /* helper */ | 368 | /* helper */ |
487 | static void | 369 | static void |
488 | chan_shutdown_write(Channel *c) | 370 | chan_shutdown_write(struct ssh *ssh, Channel *c) |
489 | { | 371 | { |
490 | buffer_clear(&c->output); | 372 | sshbuf_reset(c->output); |
491 | if (compat20 && c->type == SSH_CHANNEL_LARVAL) | 373 | if (c->type == SSH_CHANNEL_LARVAL) |
492 | return; | 374 | return; |
493 | /* shutdown failure is allowed if write failed already */ | 375 | /* shutdown failure is allowed if write failed already */ |
494 | debug2("channel %d: close_write", c->self); | 376 | debug2("channel %d: close_write", c->self); |
@@ -498,16 +380,17 @@ chan_shutdown_write(Channel *c) | |||
498 | "shutdown() failed for fd %d: %.100s", | 380 | "shutdown() failed for fd %d: %.100s", |
499 | c->self, c->sock, strerror(errno)); | 381 | c->self, c->sock, strerror(errno)); |
500 | } else { | 382 | } else { |
501 | if (channel_close_fd(&c->wfd) < 0) | 383 | if (channel_close_fd(ssh, &c->wfd) < 0) |
502 | logit("channel %d: chan_shutdown_write: " | 384 | logit("channel %d: chan_shutdown_write: " |
503 | "close() failed for fd %d: %.100s", | 385 | "close() failed for fd %d: %.100s", |
504 | c->self, c->wfd, strerror(errno)); | 386 | c->self, c->wfd, strerror(errno)); |
505 | } | 387 | } |
506 | } | 388 | } |
389 | |||
507 | static void | 390 | static void |
508 | chan_shutdown_read(Channel *c) | 391 | chan_shutdown_read(struct ssh *ssh, Channel *c) |
509 | { | 392 | { |
510 | if (compat20 && c->type == SSH_CHANNEL_LARVAL) | 393 | if (c->type == SSH_CHANNEL_LARVAL) |
511 | return; | 394 | return; |
512 | debug2("channel %d: close_read", c->self); | 395 | debug2("channel %d: close_read", c->self); |
513 | if (c->sock != -1) { | 396 | if (c->sock != -1) { |
@@ -523,7 +406,7 @@ chan_shutdown_read(Channel *c) | |||
523 | c->self, c->sock, c->istate, c->ostate, | 406 | c->self, c->sock, c->istate, c->ostate, |
524 | strerror(errno)); | 407 | strerror(errno)); |
525 | } else { | 408 | } else { |
526 | if (channel_close_fd(&c->rfd) < 0) | 409 | if (channel_close_fd(ssh, &c->rfd) < 0) |
527 | logit("channel %d: chan_shutdown_read: " | 410 | logit("channel %d: chan_shutdown_read: " |
528 | "close() failed for fd %d: %.100s", | 411 | "close() failed for fd %d: %.100s", |
529 | c->self, c->rfd, strerror(errno)); | 412 | c->self, c->rfd, strerror(errno)); |