Annotation of src/usr.bin/ssh/nchan.c, Revision 1.20
1.7 markus 1: /*
2: * Copyright (c) 1999 Markus Friedl. All rights reserved.
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.
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:
1.1 markus 25: #include "includes.h"
1.20 ! markus 26: RCSID("$OpenBSD: nchan.c,v 1.19 2000/09/07 20:27:52 deraadt Exp $");
1.2 markus 27:
1.1 markus 28: #include "ssh.h"
29:
30: #include "buffer.h"
1.3 markus 31: #include "packet.h"
1.1 markus 32: #include "channels.h"
33: #include "nchan.h"
34:
1.13 markus 35: #include "ssh2.h"
36: #include "compat.h"
1.3 markus 37:
1.13 markus 38: /* functions manipulating channel states */
1.3 markus 39: /*
1.6 markus 40: * EVENTS update channel input/output states execute ACTIONS
1.3 markus 41: */
1.13 markus 42: /* events concerning the INPUT from socket for channel (istate) */
43: chan_event_fn *chan_rcvd_oclose = NULL;
44: chan_event_fn *chan_read_failed = NULL;
45: chan_event_fn *chan_ibuf_empty = NULL;
46: /* events concerning the OUTPUT from channel for socket (ostate) */
47: chan_event_fn *chan_rcvd_ieof = NULL;
48: chan_event_fn *chan_write_failed = NULL;
49: chan_event_fn *chan_obuf_empty = NULL;
50: /*
51: * ACTIONS: should never update the channel states
52: */
53: static void chan_send_ieof1(Channel *c);
54: static void chan_send_oclose1(Channel *c);
55: static void chan_send_close2(Channel *c);
56: static void chan_send_eof2(Channel *c);
57:
58: /* channel cleanup */
59: chan_event_fn *chan_delete_if_full_closed = NULL;
60:
61: /* helper */
62: static void chan_shutdown_write(Channel *c);
63: static void chan_shutdown_read(Channel *c);
64:
65: /*
66: * SSH1 specific implementation of event functions
67: */
1.6 markus 68:
1.13 markus 69: static void
70: chan_rcvd_oclose1(Channel *c)
1.6 markus 71: {
1.13 markus 72: debug("channel %d: rcvd oclose", c->self);
1.6 markus 73: switch (c->istate) {
1.3 markus 74: case CHAN_INPUT_WAIT_OCLOSE:
1.13 markus 75: debug("channel %d: input wait_oclose -> closed", c->self);
1.6 markus 76: c->istate = CHAN_INPUT_CLOSED;
1.3 markus 77: break;
78: case CHAN_INPUT_OPEN:
1.13 markus 79: debug("channel %d: input open -> closed", c->self);
1.3 markus 80: chan_shutdown_read(c);
1.13 markus 81: chan_send_ieof1(c);
1.6 markus 82: c->istate = CHAN_INPUT_CLOSED;
1.10 markus 83: break;
84: case CHAN_INPUT_WAIT_DRAIN:
85: /* both local read_failed and remote write_failed */
1.13 markus 86: log("channel %d: input drain -> closed", c->self);
87: chan_send_ieof1(c);
1.10 markus 88: c->istate = CHAN_INPUT_CLOSED;
1.3 markus 89: break;
90: default:
1.13 markus 91: error("channel %d: protocol error: chan_rcvd_oclose for istate %d",
92: c->self, c->istate);
1.10 markus 93: return;
1.3 markus 94: }
1.1 markus 95: }
1.13 markus 96: static void
97: chan_read_failed_12(Channel *c)
1.6 markus 98: {
1.13 markus 99: debug("channel %d: read failed", c->self);
1.6 markus 100: switch (c->istate) {
1.3 markus 101: case CHAN_INPUT_OPEN:
1.13 markus 102: debug("channel %d: input open -> drain", c->self);
1.3 markus 103: chan_shutdown_read(c);
1.6 markus 104: c->istate = CHAN_INPUT_WAIT_DRAIN;
1.17 markus 105: if (buffer_len(&c->input) == 0) {
106: debug("channel %d: input: no drain shortcut", c->self);
107: chan_ibuf_empty(c);
108: }
1.3 markus 109: break;
110: default:
1.13 markus 111: error("channel %d: internal error: we do not read, but chan_read_failed for istate %d",
112: c->self, c->istate);
1.3 markus 113: break;
1.1 markus 114: }
115: }
1.13 markus 116: static void
117: chan_ibuf_empty1(Channel *c)
1.6 markus 118: {
1.13 markus 119: debug("channel %d: ibuf empty", c->self);
1.6 markus 120: if (buffer_len(&c->input)) {
1.13 markus 121: error("channel %d: internal error: chan_ibuf_empty for non empty buffer",
122: c->self);
1.3 markus 123: return;
124: }
1.6 markus 125: switch (c->istate) {
1.3 markus 126: case CHAN_INPUT_WAIT_DRAIN:
1.13 markus 127: debug("channel %d: input drain -> wait_oclose", c->self);
128: chan_send_ieof1(c);
1.6 markus 129: c->istate = CHAN_INPUT_WAIT_OCLOSE;
1.3 markus 130: break;
131: default:
1.13 markus 132: error("channel %d: internal error: chan_ibuf_empty for istate %d",
133: c->self, c->istate);
1.3 markus 134: break;
1.1 markus 135: }
136: }
1.13 markus 137: static void
138: chan_rcvd_ieof1(Channel *c)
1.6 markus 139: {
1.13 markus 140: debug("channel %d: rcvd ieof", c->self);
1.16 markus 141: if (c->type != SSH_CHANNEL_OPEN) {
142: debug("channel %d: non-open", c->self);
143: if (c->istate == CHAN_INPUT_OPEN) {
144: debug("channel %d: non-open: input open -> wait_oclose", c->self);
145: chan_shutdown_read(c);
146: chan_send_ieof1(c);
147: c->istate = CHAN_INPUT_WAIT_OCLOSE;
148: } else {
149: error("channel %d: istate %d != open", c->self, c->istate);
150: }
151: if (c->ostate == CHAN_OUTPUT_OPEN) {
152: debug("channel %d: non-open: output open -> closed", c->self);
153: chan_send_oclose1(c);
154: c->ostate = CHAN_OUTPUT_CLOSED;
155: } else {
156: error("channel %d: ostate %d != open", c->self, c->ostate);
157: }
158: return;
159: }
1.6 markus 160: switch (c->ostate) {
1.3 markus 161: case CHAN_OUTPUT_OPEN:
1.13 markus 162: debug("channel %d: output open -> drain", c->self);
1.6 markus 163: c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
1.3 markus 164: break;
165: case CHAN_OUTPUT_WAIT_IEOF:
1.13 markus 166: debug("channel %d: output wait_ieof -> closed", c->self);
1.6 markus 167: c->ostate = CHAN_OUTPUT_CLOSED;
1.3 markus 168: break;
169: default:
1.13 markus 170: error("channel %d: protocol error: chan_rcvd_ieof for ostate %d",
171: c->self, c->ostate);
1.3 markus 172: break;
173: }
174: }
1.13 markus 175: static void
176: chan_write_failed1(Channel *c)
1.6 markus 177: {
1.13 markus 178: debug("channel %d: write failed", c->self);
1.6 markus 179: switch (c->ostate) {
1.3 markus 180: case CHAN_OUTPUT_OPEN:
1.13 markus 181: debug("channel %d: output open -> wait_ieof", c->self);
182: chan_send_oclose1(c);
1.6 markus 183: c->ostate = CHAN_OUTPUT_WAIT_IEOF;
1.3 markus 184: break;
185: case CHAN_OUTPUT_WAIT_DRAIN:
1.13 markus 186: debug("channel %d: output wait_drain -> closed", c->self);
187: chan_send_oclose1(c);
1.6 markus 188: c->ostate = CHAN_OUTPUT_CLOSED;
1.3 markus 189: break;
190: default:
1.13 markus 191: error("channel %d: internal error: chan_write_failed for ostate %d",
192: c->self, c->ostate);
1.3 markus 193: break;
194: }
195: }
1.13 markus 196: static void
197: chan_obuf_empty1(Channel *c)
1.6 markus 198: {
1.13 markus 199: debug("channel %d: obuf empty", c->self);
1.6 markus 200: if (buffer_len(&c->output)) {
1.13 markus 201: error("channel %d: internal error: chan_obuf_empty for non empty buffer",
202: c->self);
1.3 markus 203: return;
204: }
1.6 markus 205: switch (c->ostate) {
1.3 markus 206: case CHAN_OUTPUT_WAIT_DRAIN:
1.13 markus 207: debug("channel %d: output drain -> closed", c->self);
208: chan_send_oclose1(c);
1.6 markus 209: c->ostate = CHAN_OUTPUT_CLOSED;
1.3 markus 210: break;
211: default:
1.13 markus 212: error("channel %d: internal error: chan_obuf_empty for ostate %d",
213: c->self, c->ostate);
1.3 markus 214: break;
215: }
216: }
217: static void
1.13 markus 218: chan_send_ieof1(Channel *c)
1.6 markus 219: {
1.13 markus 220: debug("channel %d: send ieof", c->self);
1.6 markus 221: switch (c->istate) {
1.3 markus 222: case CHAN_INPUT_OPEN:
223: case CHAN_INPUT_WAIT_DRAIN:
224: packet_start(SSH_MSG_CHANNEL_INPUT_EOF);
225: packet_put_int(c->remote_id);
226: packet_send();
227: break;
228: default:
1.13 markus 229: error("channel %d: internal error: cannot send ieof for istate %d",
230: c->self, c->istate);
1.3 markus 231: break;
1.1 markus 232: }
233: }
1.3 markus 234: static void
1.13 markus 235: chan_send_oclose1(Channel *c)
1.6 markus 236: {
1.13 markus 237: debug("channel %d: send oclose", c->self);
1.6 markus 238: switch (c->ostate) {
1.3 markus 239: case CHAN_OUTPUT_OPEN:
240: case CHAN_OUTPUT_WAIT_DRAIN:
241: chan_shutdown_write(c);
242: buffer_consume(&c->output, buffer_len(&c->output));
243: packet_start(SSH_MSG_CHANNEL_OUTPUT_CLOSE);
244: packet_put_int(c->remote_id);
245: packet_send();
246: break;
247: default:
1.13 markus 248: error("channel %d: internal error: cannot send oclose for ostate %d",
249: c->self, c->ostate);
1.3 markus 250: break;
1.1 markus 251: }
252: }
1.13 markus 253: static void
254: chan_delete_if_full_closed1(Channel *c)
255: {
1.20 ! markus 256: debug3("channel %d: chan_delete_if_full_closed1: istate %d ostate %d",
! 257: c->self, c->istate, c->ostate);
1.13 markus 258: if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {
259: debug("channel %d: full closed", c->self);
260: channel_free(c->self);
261: }
262: }
1.6 markus 263:
1.13 markus 264: /*
265: * the same for SSH2
266: */
267: static void
268: chan_rcvd_oclose2(Channel *c)
269: {
270: debug("channel %d: rcvd close", c->self);
271: if (c->flags & CHAN_CLOSE_RCVD)
272: error("channel %d: protocol error: close rcvd twice", c->self);
273: c->flags |= CHAN_CLOSE_RCVD;
274: if (c->type == SSH_CHANNEL_LARVAL) {
275: /* tear down larval channels immediately */
276: c->ostate = CHAN_OUTPUT_CLOSED;
277: c->istate = CHAN_INPUT_CLOSED;
278: return;
279: }
280: switch (c->ostate) {
281: case CHAN_OUTPUT_OPEN:
282: /* wait until a data from the channel is consumed if a CLOSE is received */
283: debug("channel %d: output open -> drain", c->self);
284: c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
285: break;
286: }
287: switch (c->istate) {
288: case CHAN_INPUT_OPEN:
289: debug("channel %d: input open -> closed", c->self);
290: chan_shutdown_read(c);
291: break;
292: case CHAN_INPUT_WAIT_DRAIN:
293: debug("channel %d: input drain -> closed", c->self);
294: chan_send_eof2(c);
295: break;
296: }
297: c->istate = CHAN_INPUT_CLOSED;
298: }
299: static void
300: chan_ibuf_empty2(Channel *c)
301: {
302: debug("channel %d: ibuf empty", c->self);
303: if (buffer_len(&c->input)) {
304: error("channel %d: internal error: chan_ibuf_empty for non empty buffer",
305: c->self);
306: return;
307: }
308: switch (c->istate) {
309: case CHAN_INPUT_WAIT_DRAIN:
310: debug("channel %d: input drain -> closed", c->self);
311: if (!(c->flags & CHAN_CLOSE_SENT))
312: chan_send_eof2(c);
313: c->istate = CHAN_INPUT_CLOSED;
314: break;
315: default:
316: error("channel %d: internal error: chan_ibuf_empty for istate %d",
317: c->self, c->istate);
318: break;
319: }
320: }
321: static void
322: chan_rcvd_ieof2(Channel *c)
323: {
324: debug("channel %d: rcvd eof", c->self);
325: if (c->ostate == CHAN_OUTPUT_OPEN) {
326: debug("channel %d: output open -> drain", c->self);
327: c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
328: }
329: }
330: static void
331: chan_write_failed2(Channel *c)
332: {
333: debug("channel %d: write failed", c->self);
334: switch (c->ostate) {
335: case CHAN_OUTPUT_OPEN:
336: debug("channel %d: output open -> closed", c->self);
1.15 markus 337: chan_shutdown_write(c); /* ?? */
1.13 markus 338: c->ostate = CHAN_OUTPUT_CLOSED;
339: break;
340: case CHAN_OUTPUT_WAIT_DRAIN:
341: debug("channel %d: output drain -> closed", c->self);
342: chan_shutdown_write(c);
343: c->ostate = CHAN_OUTPUT_CLOSED;
344: break;
345: default:
346: error("channel %d: internal error: chan_write_failed for ostate %d",
347: c->self, c->ostate);
348: break;
349: }
350: }
351: static void
352: chan_obuf_empty2(Channel *c)
353: {
354: debug("channel %d: obuf empty", c->self);
355: if (buffer_len(&c->output)) {
356: error("internal error: chan_obuf_empty %d for non empty buffer",
357: c->self);
358: return;
359: }
360: switch (c->ostate) {
361: case CHAN_OUTPUT_WAIT_DRAIN:
362: debug("channel %d: output drain -> closed", c->self);
363: chan_shutdown_write(c);
364: c->ostate = CHAN_OUTPUT_CLOSED;
365: break;
366: default:
367: error("channel %d: internal error: chan_obuf_empty for ostate %d",
368: c->self, c->ostate);
369: break;
370: }
371: }
1.3 markus 372: static void
1.13 markus 373: chan_send_eof2(Channel *c)
1.6 markus 374: {
1.13 markus 375: debug("channel %d: send eof", c->self);
376: switch (c->istate) {
377: case CHAN_INPUT_WAIT_DRAIN:
378: packet_start(SSH2_MSG_CHANNEL_EOF);
379: packet_put_int(c->remote_id);
380: packet_send();
381: break;
382: default:
383: error("channel %d: internal error: cannot send eof for istate %d",
384: c->self, c->istate);
385: break;
386: }
1.1 markus 387: }
1.3 markus 388: static void
1.13 markus 389: chan_send_close2(Channel *c)
1.6 markus 390: {
1.13 markus 391: debug("channel %d: send close", c->self);
392: if (c->ostate != CHAN_OUTPUT_CLOSED ||
393: c->istate != CHAN_INPUT_CLOSED) {
394: error("channel %d: internal error: cannot send close for istate/ostate %d/%d",
395: c->self, c->istate, c->ostate);
396: } else if (c->flags & CHAN_CLOSE_SENT) {
397: error("channel %d: internal error: already sent close", c->self);
398: } else {
399: packet_start(SSH2_MSG_CHANNEL_CLOSE);
400: packet_put_int(c->remote_id);
401: packet_send();
402: c->flags |= CHAN_CLOSE_SENT;
403: }
1.1 markus 404: }
1.13 markus 405: static void
406: chan_delete_if_full_closed2(Channel *c)
1.6 markus 407: {
1.20 ! markus 408: debug3("channel %d: chan_delete_if_full_closed2: istate %d ostate %d",
! 409: c->self, c->istate, c->ostate);
1.6 markus 410: if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {
1.13 markus 411: if (!(c->flags & CHAN_CLOSE_SENT)) {
412: chan_send_close2(c);
413: }
1.14 markus 414: if ((c->flags & CHAN_CLOSE_SENT) &&
1.13 markus 415: (c->flags & CHAN_CLOSE_RCVD)) {
416: debug("channel %d: full closed2", c->self);
417: channel_free(c->self);
1.14 markus 418: }
1.1 markus 419: }
1.3 markus 420: }
1.13 markus 421:
422: /* shared */
1.3 markus 423: void
1.6 markus 424: chan_init_iostates(Channel *c)
425: {
426: c->ostate = CHAN_OUTPUT_OPEN;
427: c->istate = CHAN_INPUT_OPEN;
1.13 markus 428: c->flags = 0;
429: }
430:
431: /* init */
432: void
433: chan_init(void)
434: {
435: if (compat20) {
436: chan_rcvd_oclose = chan_rcvd_oclose2;
437: chan_read_failed = chan_read_failed_12;
438: chan_ibuf_empty = chan_ibuf_empty2;
439:
440: chan_rcvd_ieof = chan_rcvd_ieof2;
441: chan_write_failed = chan_write_failed2;
442: chan_obuf_empty = chan_obuf_empty2;
443:
444: chan_delete_if_full_closed = chan_delete_if_full_closed2;
445: } else {
446: chan_rcvd_oclose = chan_rcvd_oclose1;
447: chan_read_failed = chan_read_failed_12;
448: chan_ibuf_empty = chan_ibuf_empty1;
449:
450: chan_rcvd_ieof = chan_rcvd_ieof1;
451: chan_write_failed = chan_write_failed1;
452: chan_obuf_empty = chan_obuf_empty1;
453:
454: chan_delete_if_full_closed = chan_delete_if_full_closed1;
455: }
456: }
457:
458: /* helper */
459: static void
460: chan_shutdown_write(Channel *c)
461: {
462: buffer_consume(&c->output, buffer_len(&c->output));
463: if (compat20 && c->type == SSH_CHANNEL_LARVAL)
464: return;
465: /* shutdown failure is allowed if write failed already */
466: debug("channel %d: close_write", c->self);
467: if (c->sock != -1) {
468: if (shutdown(c->sock, SHUT_WR) < 0)
469: debug("channel %d: chan_shutdown_write: shutdown() failed for fd%d: %.100s",
470: c->self, c->sock, strerror(errno));
471: } else {
472: if (close(c->wfd) < 0)
473: log("channel %d: chan_shutdown_write: close() failed for fd%d: %.100s",
474: c->self, c->wfd, strerror(errno));
475: c->wfd = -1;
476: }
477: }
478: static void
479: chan_shutdown_read(Channel *c)
480: {
481: if (compat20 && c->type == SSH_CHANNEL_LARVAL)
482: return;
483: debug("channel %d: close_read", c->self);
484: if (c->sock != -1) {
485: if (shutdown(c->sock, SHUT_RD) < 0)
486: error("channel %d: chan_shutdown_read: shutdown() failed for fd%d [i%d o%d]: %.100s",
487: c->self, c->sock, c->istate, c->ostate, strerror(errno));
488: } else {
489: if (close(c->rfd) < 0)
490: log("channel %d: chan_shutdown_read: close() failed for fd%d: %.100s",
491: c->self, c->rfd, strerror(errno));
492: c->rfd = -1;
493: }
1.1 markus 494: }