]> andersk Git - openssh.git/blame - nchan.c
- markus@cvs.openbsd.org 2002/01/10 12:47:59
[openssh.git] / nchan.c
CommitLineData
aa3378df 1/*
a96070d4 2 * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved.
aa3378df 3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
aa3378df 12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
8efc0c15 25#include "includes.h"
6d566d33 26RCSID("$OpenBSD: nchan.c,v 1.36 2002/01/10 12:47:59 markus Exp $");
8efc0c15 27
42f11eb2 28#include "ssh1.h"
29#include "ssh2.h"
8efc0c15 30#include "buffer.h"
31#include "packet.h"
32#include "channels.h"
7e7327a1 33#include "compat.h"
42f11eb2 34#include "log.h"
8efc0c15 35
f048f3e2 36/*
37 * SSH Protocol 1.5 aka New Channel Protocol
38 * Thanks to Martina, Axel and everyone who left Erlangen, leaving me bored.
39 * Written by Markus Friedl in October 1999
40 *
41 * Protocol versions 1.3 and 1.5 differ in the handshake protocol used for the
42 * tear down of channels:
43 *
44 * 1.3: strict request-ack-protocol:
45 * CLOSE ->
46 * <- CLOSE_CONFIRM
47 *
48 * 1.5: uses variations of:
49 * IEOF ->
50 * <- OCLOSE
51 * <- IEOF
52 * OCLOSE ->
53 * i.e. both sides have to close the channel
54 *
55 * 2.0: the EOF messages are optional
56 *
57 * See the debugging output from 'ssh -v' and 'sshd -d' of
58 * ssh-1.2.27 as an example.
59 *
60 */
1b73841d 61
7e7327a1 62/* functions manipulating channel states */
8efc0c15 63/*
5260325f 64 * EVENTS update channel input/output states execute ACTIONS
8efc0c15 65 */
66/* events concerning the INPUT from socket for channel (istate) */
7e7327a1 67chan_event_fn *chan_rcvd_oclose = NULL;
68chan_event_fn *chan_read_failed = NULL;
69chan_event_fn *chan_ibuf_empty = NULL;
70/* events concerning the OUTPUT from channel for socket (ostate) */
71chan_event_fn *chan_rcvd_ieof = NULL;
72chan_event_fn *chan_write_failed = NULL;
73chan_event_fn *chan_obuf_empty = NULL;
74/*
75 * ACTIONS: should never update the channel states
76 */
396c147e 77static void chan_send_ieof1(Channel *);
78static void chan_send_oclose1(Channel *);
79static void chan_send_close2(Channel *);
80static void chan_send_eof2(Channel *);
7e7327a1 81
7e7327a1 82/* helper */
396c147e 83static void chan_shutdown_write(Channel *);
84static void chan_shutdown_read(Channel *);
7e7327a1 85
86/*
87 * SSH1 specific implementation of event functions
88 */
89
90static void
91chan_rcvd_oclose1(Channel *c)
5260325f 92{
7e7327a1 93 debug("channel %d: rcvd oclose", c->self);
5260325f 94 switch (c->istate) {
8efc0c15 95 case CHAN_INPUT_WAIT_OCLOSE:
7e7327a1 96 debug("channel %d: input wait_oclose -> closed", c->self);
5260325f 97 c->istate = CHAN_INPUT_CLOSED;
8efc0c15 98 break;
99 case CHAN_INPUT_OPEN:
7e7327a1 100 debug("channel %d: input open -> closed", c->self);
8efc0c15 101 chan_shutdown_read(c);
7e7327a1 102 chan_send_ieof1(c);
5260325f 103 c->istate = CHAN_INPUT_CLOSED;
48e671d5 104 break;
105 case CHAN_INPUT_WAIT_DRAIN:
106 /* both local read_failed and remote write_failed */
7e7327a1 107 log("channel %d: input drain -> closed", c->self);
108 chan_send_ieof1(c);
48e671d5 109 c->istate = CHAN_INPUT_CLOSED;
8efc0c15 110 break;
111 default:
f048f3e2 112 error("channel %d: protocol error: rcvd_oclose for istate %d",
7e7327a1 113 c->self, c->istate);
48e671d5 114 return;
8efc0c15 115 }
116}
7e7327a1 117static void
118chan_read_failed_12(Channel *c)
5260325f 119{
7e7327a1 120 debug("channel %d: read failed", c->self);
5260325f 121 switch (c->istate) {
8efc0c15 122 case CHAN_INPUT_OPEN:
7e7327a1 123 debug("channel %d: input open -> drain", c->self);
8efc0c15 124 chan_shutdown_read(c);
5260325f 125 c->istate = CHAN_INPUT_WAIT_DRAIN;
8efc0c15 126 break;
127 default:
f048f3e2 128 error("channel %d: chan_read_failed for istate %d",
7e7327a1 129 c->self, c->istate);
8efc0c15 130 break;
131 }
132}
7e7327a1 133static void
134chan_ibuf_empty1(Channel *c)
5260325f 135{
7e7327a1 136 debug("channel %d: ibuf empty", c->self);
5260325f 137 if (buffer_len(&c->input)) {
f048f3e2 138 error("channel %d: chan_ibuf_empty for non empty buffer",
7e7327a1 139 c->self);
8efc0c15 140 return;
141 }
5260325f 142 switch (c->istate) {
8efc0c15 143 case CHAN_INPUT_WAIT_DRAIN:
7e7327a1 144 debug("channel %d: input drain -> wait_oclose", c->self);
145 chan_send_ieof1(c);
5260325f 146 c->istate = CHAN_INPUT_WAIT_OCLOSE;
8efc0c15 147 break;
148 default:
f048f3e2 149 error("channel %d: chan_ibuf_empty for istate %d",
7e7327a1 150 c->self, c->istate);
8efc0c15 151 break;
152 }
153}
7e7327a1 154static void
155chan_rcvd_ieof1(Channel *c)
5260325f 156{
7e7327a1 157 debug("channel %d: rcvd ieof", c->self);
5260325f 158 switch (c->ostate) {
8efc0c15 159 case CHAN_OUTPUT_OPEN:
7e7327a1 160 debug("channel %d: output open -> drain", c->self);
5260325f 161 c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
8efc0c15 162 break;
163 case CHAN_OUTPUT_WAIT_IEOF:
7e7327a1 164 debug("channel %d: output wait_ieof -> closed", c->self);
5260325f 165 c->ostate = CHAN_OUTPUT_CLOSED;
8efc0c15 166 break;
167 default:
f048f3e2 168 error("channel %d: protocol error: rcvd_ieof for ostate %d",
7e7327a1 169 c->self, c->ostate);
8efc0c15 170 break;
171 }
172}
7e7327a1 173static void
174chan_write_failed1(Channel *c)
5260325f 175{
7e7327a1 176 debug("channel %d: write failed", c->self);
5260325f 177 switch (c->ostate) {
8efc0c15 178 case CHAN_OUTPUT_OPEN:
7e7327a1 179 debug("channel %d: output open -> wait_ieof", c->self);
180 chan_send_oclose1(c);
5260325f 181 c->ostate = CHAN_OUTPUT_WAIT_IEOF;
8efc0c15 182 break;
183 case CHAN_OUTPUT_WAIT_DRAIN:
7e7327a1 184 debug("channel %d: output wait_drain -> closed", c->self);
185 chan_send_oclose1(c);
5260325f 186 c->ostate = CHAN_OUTPUT_CLOSED;
8efc0c15 187 break;
188 default:
f048f3e2 189 error("channel %d: chan_write_failed for ostate %d",
7e7327a1 190 c->self, c->ostate);
8efc0c15 191 break;
192 }
193}
7e7327a1 194static void
195chan_obuf_empty1(Channel *c)
5260325f 196{
7e7327a1 197 debug("channel %d: obuf empty", c->self);
5260325f 198 if (buffer_len(&c->output)) {
f048f3e2 199 error("channel %d: chan_obuf_empty for non empty buffer",
7e7327a1 200 c->self);
8efc0c15 201 return;
202 }
5260325f 203 switch (c->ostate) {
8efc0c15 204 case CHAN_OUTPUT_WAIT_DRAIN:
7e7327a1 205 debug("channel %d: output drain -> closed", c->self);
206 chan_send_oclose1(c);
5260325f 207 c->ostate = CHAN_OUTPUT_CLOSED;
8efc0c15 208 break;
209 default:
f048f3e2 210 error("channel %d: internal error: obuf_empty for ostate %d",
7e7327a1 211 c->self, c->ostate);
8efc0c15 212 break;
213 }
214}
8efc0c15 215static void
7e7327a1 216chan_send_ieof1(Channel *c)
5260325f 217{
7e7327a1 218 debug("channel %d: send ieof", c->self);
5260325f 219 switch (c->istate) {
8efc0c15 220 case CHAN_INPUT_OPEN:
221 case CHAN_INPUT_WAIT_DRAIN:
222 packet_start(SSH_MSG_CHANNEL_INPUT_EOF);
223 packet_put_int(c->remote_id);
224 packet_send();
225 break;
226 default:
f048f3e2 227 error("channel %d: cannot send ieof for istate %d",
7e7327a1 228 c->self, c->istate);
8efc0c15 229 break;
230 }
231}
232static void
7e7327a1 233chan_send_oclose1(Channel *c)
5260325f 234{
7e7327a1 235 debug("channel %d: send oclose", c->self);
5260325f 236 switch (c->ostate) {
8efc0c15 237 case CHAN_OUTPUT_OPEN:
238 case CHAN_OUTPUT_WAIT_DRAIN:
239 chan_shutdown_write(c);
9c50edcf 240 buffer_clear(&c->output);
8efc0c15 241 packet_start(SSH_MSG_CHANNEL_OUTPUT_CLOSE);
242 packet_put_int(c->remote_id);
243 packet_send();
244 break;
245 default:
f048f3e2 246 error("channel %d: cannot send oclose for ostate %d",
184eed6a 247 c->self, c->ostate);
8efc0c15 248 break;
249 }
250}
5260325f 251
7e7327a1 252/*
253 * the same for SSH2
254 */
8efc0c15 255static void
7e7327a1 256chan_rcvd_oclose2(Channel *c)
5260325f 257{
7e7327a1 258 debug("channel %d: rcvd close", c->self);
259 if (c->flags & CHAN_CLOSE_RCVD)
260 error("channel %d: protocol error: close rcvd twice", c->self);
261 c->flags |= CHAN_CLOSE_RCVD;
262 if (c->type == SSH_CHANNEL_LARVAL) {
263 /* tear down larval channels immediately */
264 c->ostate = CHAN_OUTPUT_CLOSED;
265 c->istate = CHAN_INPUT_CLOSED;
266 return;
267 }
268 switch (c->ostate) {
269 case CHAN_OUTPUT_OPEN:
f048f3e2 270 /*
271 * wait until a data from the channel is consumed if a CLOSE
272 * is received
273 */
7e7327a1 274 debug("channel %d: output open -> drain", c->self);
275 c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
276 break;
277 }
278 switch (c->istate) {
279 case CHAN_INPUT_OPEN:
280 debug("channel %d: input open -> closed", c->self);
281 chan_shutdown_read(c);
282 break;
283 case CHAN_INPUT_WAIT_DRAIN:
284 debug("channel %d: input drain -> closed", c->self);
285 chan_send_eof2(c);
286 break;
287 }
288 c->istate = CHAN_INPUT_CLOSED;
8efc0c15 289}
290static void
7e7327a1 291chan_ibuf_empty2(Channel *c)
292{
293 debug("channel %d: ibuf empty", c->self);
294 if (buffer_len(&c->input)) {
f048f3e2 295 error("channel %d: chan_ibuf_empty for non empty buffer",
184eed6a 296 c->self);
7e7327a1 297 return;
298 }
299 switch (c->istate) {
300 case CHAN_INPUT_WAIT_DRAIN:
301 debug("channel %d: input drain -> closed", c->self);
302 if (!(c->flags & CHAN_CLOSE_SENT))
303 chan_send_eof2(c);
304 c->istate = CHAN_INPUT_CLOSED;
305 break;
306 default:
f048f3e2 307 error("channel %d: chan_ibuf_empty for istate %d",
184eed6a 308 c->self, c->istate);
7e7327a1 309 break;
310 }
311}
312static void
313chan_rcvd_ieof2(Channel *c)
5260325f 314{
7e7327a1 315 debug("channel %d: rcvd eof", c->self);
316 if (c->ostate == CHAN_OUTPUT_OPEN) {
317 debug("channel %d: output open -> drain", c->self);
318 c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
319 }
8efc0c15 320}
7e7327a1 321static void
322chan_write_failed2(Channel *c)
323{
324 debug("channel %d: write failed", c->self);
325 switch (c->ostate) {
326 case CHAN_OUTPUT_OPEN:
327 debug("channel %d: output open -> closed", c->self);
1d1ffb87 328 chan_shutdown_write(c); /* ?? */
7e7327a1 329 c->ostate = CHAN_OUTPUT_CLOSED;
330 break;
331 case CHAN_OUTPUT_WAIT_DRAIN:
332 debug("channel %d: output drain -> closed", c->self);
333 chan_shutdown_write(c);
334 c->ostate = CHAN_OUTPUT_CLOSED;
335 break;
336 default:
f048f3e2 337 error("channel %d: chan_write_failed for ostate %d",
7e7327a1 338 c->self, c->ostate);
339 break;
340 }
341}
342static void
343chan_obuf_empty2(Channel *c)
344{
345 debug("channel %d: obuf empty", c->self);
346 if (buffer_len(&c->output)) {
f048f3e2 347 error("channel %d: chan_obuf_empty for non empty buffer",
7e7327a1 348 c->self);
349 return;
350 }
351 switch (c->ostate) {
352 case CHAN_OUTPUT_WAIT_DRAIN:
353 debug("channel %d: output drain -> closed", c->self);
354 chan_shutdown_write(c);
355 c->ostate = CHAN_OUTPUT_CLOSED;
356 break;
357 default:
f048f3e2 358 error("channel %d: chan_obuf_empty for ostate %d",
7e7327a1 359 c->self, c->ostate);
360 break;
361 }
362}
363static void
364chan_send_eof2(Channel *c)
365{
366 debug("channel %d: send eof", c->self);
367 switch (c->istate) {
368 case CHAN_INPUT_WAIT_DRAIN:
369 packet_start(SSH2_MSG_CHANNEL_EOF);
370 packet_put_int(c->remote_id);
371 packet_send();
372 break;
373 default:
f048f3e2 374 error("channel %d: cannot send eof for istate %d",
7e7327a1 375 c->self, c->istate);
376 break;
377 }
378}
379static void
380chan_send_close2(Channel *c)
381{
382 debug("channel %d: send close", c->self);
383 if (c->ostate != CHAN_OUTPUT_CLOSED ||
384 c->istate != CHAN_INPUT_CLOSED) {
f048f3e2 385 error("channel %d: cannot send close for istate/ostate %d/%d",
7e7327a1 386 c->self, c->istate, c->ostate);
387 } else if (c->flags & CHAN_CLOSE_SENT) {
f048f3e2 388 error("channel %d: already sent close", c->self);
7e7327a1 389 } else {
390 packet_start(SSH2_MSG_CHANNEL_CLOSE);
391 packet_put_int(c->remote_id);
392 packet_send();
393 c->flags |= CHAN_CLOSE_SENT;
394 }
395}
ee55dacf 396
397/* shared */
398
719fc62f 399void
400chan_mark_dead(Channel *c)
401{
6fd8622b 402 c->type = SSH_CHANNEL_ZOMBIE;
719fc62f 403}
404
ee55dacf 405int
418e724c 406chan_is_dead(Channel *c, int send)
5260325f 407{
6fd8622b 408 if (c->type == SSH_CHANNEL_ZOMBIE) {
409 debug("channel %d: zombie", c->self);
719fc62f 410 return 1;
6fd8622b 411 }
ee55dacf 412 if (c->istate != CHAN_INPUT_CLOSED || c->ostate != CHAN_OUTPUT_CLOSED)
413 return 0;
414 if (!compat20) {
415 debug("channel %d: is dead", c->self);
416 return 1;
417 }
418 /*
419 * we have to delay the close message if the efd (for stderr) is
420 * still active
421 */
422 if (((c->extended_usage != CHAN_EXTENDED_IGNORE) &&
423 buffer_len(&c->extended) > 0)
424#if 0
425 || ((c->extended_usage == CHAN_EXTENDED_READ) &&
426 c->efd != -1)
427#endif
428 ) {
429 debug2("channel %d: active efd: %d len %d type %s",
430 c->self, c->efd, buffer_len(&c->extended),
431 c->extended_usage==CHAN_EXTENDED_READ ?
184eed6a 432 "read": "write");
ee55dacf 433 } else {
7e7327a1 434 if (!(c->flags & CHAN_CLOSE_SENT)) {
418e724c 435 if (send) {
436 chan_send_close2(c);
437 } else {
438 /* channel would be dead if we sent a close */
439 if (c->flags & CHAN_CLOSE_RCVD) {
440 debug("channel %d: almost dead",
441 c->self);
442 return 1;
443 }
444 }
7e7327a1 445 }
6ae2364d 446 if ((c->flags & CHAN_CLOSE_SENT) &&
7e7327a1 447 (c->flags & CHAN_CLOSE_RCVD)) {
ee55dacf 448 debug("channel %d: is dead", c->self);
449 return 1;
6ae2364d 450 }
8efc0c15 451 }
ee55dacf 452 return 0;
8efc0c15 453}
7e7327a1 454
8efc0c15 455void
5260325f 456chan_init_iostates(Channel *c)
457{
458 c->ostate = CHAN_OUTPUT_OPEN;
459 c->istate = CHAN_INPUT_OPEN;
7e7327a1 460 c->flags = 0;
461}
462
463/* init */
464void
465chan_init(void)
466{
467 if (compat20) {
468 chan_rcvd_oclose = chan_rcvd_oclose2;
469 chan_read_failed = chan_read_failed_12;
470 chan_ibuf_empty = chan_ibuf_empty2;
471
472 chan_rcvd_ieof = chan_rcvd_ieof2;
473 chan_write_failed = chan_write_failed2;
474 chan_obuf_empty = chan_obuf_empty2;
7e7327a1 475 } else {
476 chan_rcvd_oclose = chan_rcvd_oclose1;
477 chan_read_failed = chan_read_failed_12;
478 chan_ibuf_empty = chan_ibuf_empty1;
479
480 chan_rcvd_ieof = chan_rcvd_ieof1;
481 chan_write_failed = chan_write_failed1;
482 chan_obuf_empty = chan_obuf_empty1;
7e7327a1 483 }
484}
485
486/* helper */
487static void
488chan_shutdown_write(Channel *c)
489{
9c50edcf 490 buffer_clear(&c->output);
7e7327a1 491 if (compat20 && c->type == SSH_CHANNEL_LARVAL)
492 return;
493 /* shutdown failure is allowed if write failed already */
494 debug("channel %d: close_write", c->self);
495 if (c->sock != -1) {
496 if (shutdown(c->sock, SHUT_WR) < 0)
f048f3e2 497 debug("channel %d: chan_shutdown_write: "
498 "shutdown() failed for fd%d: %.100s",
7e7327a1 499 c->self, c->sock, strerror(errno));
500 } else {
489aa2e9 501 if (channel_close_fd(&c->wfd) < 0)
f048f3e2 502 log("channel %d: chan_shutdown_write: "
503 "close() failed for fd%d: %.100s",
7e7327a1 504 c->self, c->wfd, strerror(errno));
7e7327a1 505 }
506}
507static void
508chan_shutdown_read(Channel *c)
509{
510 if (compat20 && c->type == SSH_CHANNEL_LARVAL)
511 return;
512 debug("channel %d: close_read", c->self);
513 if (c->sock != -1) {
2b87da3b 514 /*
47670e77 515 * shutdown(sock, SHUT_READ) may return ENOTCONN if the
516 * write side has been closed already. (bug on Linux)
f49df8e9 517 * HP-UX may return ENOTCONN also.
47670e77 518 */
519 if (shutdown(c->sock, SHUT_RD) < 0
f49df8e9 520 && errno != ENOTCONN)
f048f3e2 521 error("channel %d: chan_shutdown_read: "
522 "shutdown() failed for fd%d [i%d o%d]: %.100s",
523 c->self, c->sock, c->istate, c->ostate,
1b73841d 524 strerror(errno));
7e7327a1 525 } else {
489aa2e9 526 if (channel_close_fd(&c->rfd) < 0)
f048f3e2 527 log("channel %d: chan_shutdown_read: "
528 "close() failed for fd%d: %.100s",
7e7327a1 529 c->self, c->rfd, strerror(errno));
7e7327a1 530 }
8efc0c15 531}
This page took 0.757152 seconds and 5 git commands to generate.