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