Annotation of src/usr.bin/ssh/nchan.c, Revision 1.15
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: * 3. All advertising materials mentioning features or use of this software
13: * must display the following acknowledgement:
14: * This product includes software developed by Markus Friedl.
15: * 4. The name of the author may not be used to endorse or promote products
16: * derived from this software without specific prior written permission.
17: *
18: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28: */
29:
1.1 markus 30: #include "includes.h"
1.15 ! markus 31: RCSID("$Id: nchan.c,v 1.14 2000/04/14 10:30:32 markus Exp $");
1.2 markus 32:
1.1 markus 33: #include "ssh.h"
34:
35: #include "buffer.h"
1.3 markus 36: #include "packet.h"
1.1 markus 37: #include "channels.h"
38: #include "nchan.h"
39:
1.13 markus 40: #include "ssh2.h"
41: #include "compat.h"
1.3 markus 42:
1.13 markus 43: /* functions manipulating channel states */
1.3 markus 44: /*
1.6 markus 45: * EVENTS update channel input/output states execute ACTIONS
1.3 markus 46: */
1.13 markus 47: /* events concerning the INPUT from socket for channel (istate) */
48: chan_event_fn *chan_rcvd_oclose = NULL;
49: chan_event_fn *chan_read_failed = NULL;
50: chan_event_fn *chan_ibuf_empty = NULL;
51: /* events concerning the OUTPUT from channel for socket (ostate) */
52: chan_event_fn *chan_rcvd_ieof = NULL;
53: chan_event_fn *chan_write_failed = NULL;
54: chan_event_fn *chan_obuf_empty = NULL;
55: /*
56: * ACTIONS: should never update the channel states
57: */
58: static void chan_send_ieof1(Channel *c);
59: static void chan_send_oclose1(Channel *c);
60: static void chan_send_close2(Channel *c);
61: static void chan_send_eof2(Channel *c);
62:
63: /* channel cleanup */
64: chan_event_fn *chan_delete_if_full_closed = NULL;
65:
66: /* helper */
67: static void chan_shutdown_write(Channel *c);
68: static void chan_shutdown_read(Channel *c);
69:
70: /*
71: * SSH1 specific implementation of event functions
72: */
1.6 markus 73:
1.13 markus 74: static void
75: chan_rcvd_oclose1(Channel *c)
1.6 markus 76: {
1.13 markus 77: debug("channel %d: rcvd oclose", c->self);
1.6 markus 78: switch (c->istate) {
1.3 markus 79: case CHAN_INPUT_WAIT_OCLOSE:
1.13 markus 80: debug("channel %d: input wait_oclose -> closed", c->self);
1.6 markus 81: c->istate = CHAN_INPUT_CLOSED;
1.3 markus 82: break;
83: case CHAN_INPUT_OPEN:
1.13 markus 84: debug("channel %d: input open -> closed", c->self);
1.3 markus 85: chan_shutdown_read(c);
1.13 markus 86: chan_send_ieof1(c);
1.6 markus 87: c->istate = CHAN_INPUT_CLOSED;
1.10 markus 88: break;
89: case CHAN_INPUT_WAIT_DRAIN:
90: /* both local read_failed and remote write_failed */
1.13 markus 91: log("channel %d: input drain -> closed", c->self);
92: chan_send_ieof1(c);
1.10 markus 93: c->istate = CHAN_INPUT_CLOSED;
1.3 markus 94: break;
95: default:
1.13 markus 96: error("channel %d: protocol error: chan_rcvd_oclose for istate %d",
97: c->self, c->istate);
1.10 markus 98: return;
1.3 markus 99: }
1.1 markus 100: }
1.13 markus 101: static void
102: chan_read_failed_12(Channel *c)
1.6 markus 103: {
1.13 markus 104: debug("channel %d: read failed", c->self);
1.6 markus 105: switch (c->istate) {
1.3 markus 106: case CHAN_INPUT_OPEN:
1.13 markus 107: debug("channel %d: input open -> drain", c->self);
1.3 markus 108: chan_shutdown_read(c);
1.6 markus 109: c->istate = CHAN_INPUT_WAIT_DRAIN;
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.6 markus 142: switch (c->ostate) {
1.3 markus 143: case CHAN_OUTPUT_OPEN:
1.13 markus 144: debug("channel %d: output open -> drain", c->self);
1.6 markus 145: c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
1.3 markus 146: break;
147: case CHAN_OUTPUT_WAIT_IEOF:
1.13 markus 148: debug("channel %d: output wait_ieof -> closed", c->self);
1.6 markus 149: c->ostate = CHAN_OUTPUT_CLOSED;
1.3 markus 150: break;
151: default:
1.13 markus 152: error("channel %d: protocol error: chan_rcvd_ieof for ostate %d",
153: c->self, c->ostate);
1.3 markus 154: break;
155: }
156: }
1.13 markus 157: static void
158: chan_write_failed1(Channel *c)
1.6 markus 159: {
1.13 markus 160: debug("channel %d: write failed", c->self);
1.6 markus 161: switch (c->ostate) {
1.3 markus 162: case CHAN_OUTPUT_OPEN:
1.13 markus 163: debug("channel %d: output open -> wait_ieof", c->self);
164: chan_send_oclose1(c);
1.6 markus 165: c->ostate = CHAN_OUTPUT_WAIT_IEOF;
1.3 markus 166: break;
167: case CHAN_OUTPUT_WAIT_DRAIN:
1.13 markus 168: debug("channel %d: output wait_drain -> closed", c->self);
169: chan_send_oclose1(c);
1.6 markus 170: c->ostate = CHAN_OUTPUT_CLOSED;
1.3 markus 171: break;
172: default:
1.13 markus 173: error("channel %d: internal error: chan_write_failed for ostate %d",
174: c->self, c->ostate);
1.3 markus 175: break;
176: }
177: }
1.13 markus 178: static void
179: chan_obuf_empty1(Channel *c)
1.6 markus 180: {
1.13 markus 181: debug("channel %d: obuf empty", c->self);
1.6 markus 182: if (buffer_len(&c->output)) {
1.13 markus 183: error("channel %d: internal error: chan_obuf_empty for non empty buffer",
184: c->self);
1.3 markus 185: return;
186: }
1.6 markus 187: switch (c->ostate) {
1.3 markus 188: case CHAN_OUTPUT_WAIT_DRAIN:
1.13 markus 189: debug("channel %d: output drain -> closed", c->self);
190: chan_send_oclose1(c);
1.6 markus 191: c->ostate = CHAN_OUTPUT_CLOSED;
1.3 markus 192: break;
193: default:
1.13 markus 194: error("channel %d: internal error: chan_obuf_empty for ostate %d",
195: c->self, c->ostate);
1.3 markus 196: break;
197: }
198: }
199: static void
1.13 markus 200: chan_send_ieof1(Channel *c)
1.6 markus 201: {
1.13 markus 202: debug("channel %d: send ieof", c->self);
1.6 markus 203: switch (c->istate) {
1.3 markus 204: case CHAN_INPUT_OPEN:
205: case CHAN_INPUT_WAIT_DRAIN:
206: packet_start(SSH_MSG_CHANNEL_INPUT_EOF);
207: packet_put_int(c->remote_id);
208: packet_send();
209: break;
210: default:
1.13 markus 211: error("channel %d: internal error: cannot send ieof for istate %d",
212: c->self, c->istate);
1.3 markus 213: break;
1.1 markus 214: }
215: }
1.3 markus 216: static void
1.13 markus 217: chan_send_oclose1(Channel *c)
1.6 markus 218: {
1.13 markus 219: debug("channel %d: send oclose", c->self);
1.6 markus 220: switch (c->ostate) {
1.3 markus 221: case CHAN_OUTPUT_OPEN:
222: case CHAN_OUTPUT_WAIT_DRAIN:
223: chan_shutdown_write(c);
224: buffer_consume(&c->output, buffer_len(&c->output));
225: packet_start(SSH_MSG_CHANNEL_OUTPUT_CLOSE);
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 oclose for ostate %d",
231: c->self, c->ostate);
1.3 markus 232: break;
1.1 markus 233: }
234: }
1.13 markus 235: static void
236: chan_delete_if_full_closed1(Channel *c)
237: {
238: if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {
239: debug("channel %d: full closed", c->self);
240: channel_free(c->self);
241: }
242: }
1.6 markus 243:
1.13 markus 244: /*
245: * the same for SSH2
246: */
247: static void
248: chan_rcvd_oclose2(Channel *c)
249: {
250: debug("channel %d: rcvd close", c->self);
251: if (c->flags & CHAN_CLOSE_RCVD)
252: error("channel %d: protocol error: close rcvd twice", c->self);
253: c->flags |= CHAN_CLOSE_RCVD;
254: if (c->type == SSH_CHANNEL_LARVAL) {
255: /* tear down larval channels immediately */
256: c->ostate = CHAN_OUTPUT_CLOSED;
257: c->istate = CHAN_INPUT_CLOSED;
258: return;
259: }
260: switch (c->ostate) {
261: case CHAN_OUTPUT_OPEN:
262: /* wait until a data from the channel is consumed if a CLOSE is received */
263: debug("channel %d: output open -> drain", c->self);
264: c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
265: break;
266: }
267: switch (c->istate) {
268: case CHAN_INPUT_OPEN:
269: debug("channel %d: input open -> closed", c->self);
270: chan_shutdown_read(c);
271: break;
272: case CHAN_INPUT_WAIT_DRAIN:
273: debug("channel %d: input drain -> closed", c->self);
274: chan_send_eof2(c);
275: break;
276: }
277: c->istate = CHAN_INPUT_CLOSED;
278: }
279: static void
280: chan_ibuf_empty2(Channel *c)
281: {
282: debug("channel %d: ibuf empty", c->self);
283: if (buffer_len(&c->input)) {
284: error("channel %d: internal error: chan_ibuf_empty for non empty buffer",
285: c->self);
286: return;
287: }
288: switch (c->istate) {
289: case CHAN_INPUT_WAIT_DRAIN:
290: debug("channel %d: input drain -> closed", c->self);
291: if (!(c->flags & CHAN_CLOSE_SENT))
292: chan_send_eof2(c);
293: c->istate = CHAN_INPUT_CLOSED;
294: break;
295: default:
296: error("channel %d: internal error: chan_ibuf_empty for istate %d",
297: c->self, c->istate);
298: break;
299: }
300: }
301: static void
302: chan_rcvd_ieof2(Channel *c)
303: {
304: debug("channel %d: rcvd eof", c->self);
305: if (c->ostate == CHAN_OUTPUT_OPEN) {
306: debug("channel %d: output open -> drain", c->self);
307: c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
308: }
309: }
310: static void
311: chan_write_failed2(Channel *c)
312: {
313: debug("channel %d: write failed", c->self);
314: switch (c->ostate) {
315: case CHAN_OUTPUT_OPEN:
316: debug("channel %d: output open -> closed", c->self);
1.15 ! markus 317: chan_shutdown_write(c); /* ?? */
1.13 markus 318: c->ostate = CHAN_OUTPUT_CLOSED;
319: break;
320: case CHAN_OUTPUT_WAIT_DRAIN:
321: debug("channel %d: output drain -> closed", c->self);
322: chan_shutdown_write(c);
323: c->ostate = CHAN_OUTPUT_CLOSED;
324: break;
325: default:
326: error("channel %d: internal error: chan_write_failed for ostate %d",
327: c->self, c->ostate);
328: break;
329: }
330: }
331: static void
332: chan_obuf_empty2(Channel *c)
333: {
334: debug("channel %d: obuf empty", c->self);
335: if (buffer_len(&c->output)) {
336: error("internal error: chan_obuf_empty %d for non empty buffer",
337: c->self);
338: return;
339: }
340: switch (c->ostate) {
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_obuf_empty for ostate %d",
348: c->self, c->ostate);
349: break;
350: }
351: }
1.3 markus 352: static void
1.13 markus 353: chan_send_eof2(Channel *c)
1.6 markus 354: {
1.13 markus 355: debug("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: break;
362: default:
363: error("channel %d: internal error: cannot send eof for istate %d",
364: c->self, c->istate);
365: break;
366: }
1.1 markus 367: }
1.3 markus 368: static void
1.13 markus 369: chan_send_close2(Channel *c)
1.6 markus 370: {
1.13 markus 371: debug("channel %d: send close", c->self);
372: if (c->ostate != CHAN_OUTPUT_CLOSED ||
373: c->istate != CHAN_INPUT_CLOSED) {
374: error("channel %d: internal error: cannot send close for istate/ostate %d/%d",
375: c->self, c->istate, c->ostate);
376: } else if (c->flags & CHAN_CLOSE_SENT) {
377: error("channel %d: internal error: already sent close", c->self);
378: } else {
379: packet_start(SSH2_MSG_CHANNEL_CLOSE);
380: packet_put_int(c->remote_id);
381: packet_send();
382: c->flags |= CHAN_CLOSE_SENT;
383: }
1.1 markus 384: }
1.13 markus 385: static void
386: chan_delete_if_full_closed2(Channel *c)
1.6 markus 387: {
388: if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {
1.13 markus 389: if (!(c->flags & CHAN_CLOSE_SENT)) {
390: chan_send_close2(c);
391: }
1.14 markus 392: if ((c->flags & CHAN_CLOSE_SENT) &&
1.13 markus 393: (c->flags & CHAN_CLOSE_RCVD)) {
394: debug("channel %d: full closed2", c->self);
395: channel_free(c->self);
1.14 markus 396: }
1.1 markus 397: }
1.3 markus 398: }
1.13 markus 399:
400: /* shared */
1.3 markus 401: void
1.6 markus 402: chan_init_iostates(Channel *c)
403: {
404: c->ostate = CHAN_OUTPUT_OPEN;
405: c->istate = CHAN_INPUT_OPEN;
1.13 markus 406: c->flags = 0;
407: }
408:
409: /* init */
410: void
411: chan_init(void)
412: {
413: if (compat20) {
414: chan_rcvd_oclose = chan_rcvd_oclose2;
415: chan_read_failed = chan_read_failed_12;
416: chan_ibuf_empty = chan_ibuf_empty2;
417:
418: chan_rcvd_ieof = chan_rcvd_ieof2;
419: chan_write_failed = chan_write_failed2;
420: chan_obuf_empty = chan_obuf_empty2;
421:
422: chan_delete_if_full_closed = chan_delete_if_full_closed2;
423: } else {
424: chan_rcvd_oclose = chan_rcvd_oclose1;
425: chan_read_failed = chan_read_failed_12;
426: chan_ibuf_empty = chan_ibuf_empty1;
427:
428: chan_rcvd_ieof = chan_rcvd_ieof1;
429: chan_write_failed = chan_write_failed1;
430: chan_obuf_empty = chan_obuf_empty1;
431:
432: chan_delete_if_full_closed = chan_delete_if_full_closed1;
433: }
434: }
435:
436: /* helper */
437: static void
438: chan_shutdown_write(Channel *c)
439: {
440: buffer_consume(&c->output, buffer_len(&c->output));
441: if (compat20 && c->type == SSH_CHANNEL_LARVAL)
442: return;
443: /* shutdown failure is allowed if write failed already */
444: debug("channel %d: close_write", c->self);
445: if (c->sock != -1) {
446: if (shutdown(c->sock, SHUT_WR) < 0)
447: debug("channel %d: chan_shutdown_write: shutdown() failed for fd%d: %.100s",
448: c->self, c->sock, strerror(errno));
449: } else {
450: if (close(c->wfd) < 0)
451: log("channel %d: chan_shutdown_write: close() failed for fd%d: %.100s",
452: c->self, c->wfd, strerror(errno));
453: c->wfd = -1;
454: }
455: }
456: static void
457: chan_shutdown_read(Channel *c)
458: {
459: if (compat20 && c->type == SSH_CHANNEL_LARVAL)
460: return;
461: debug("channel %d: close_read", c->self);
462: if (c->sock != -1) {
463: if (shutdown(c->sock, SHUT_RD) < 0)
464: error("channel %d: chan_shutdown_read: shutdown() failed for fd%d [i%d o%d]: %.100s",
465: c->self, c->sock, c->istate, c->ostate, strerror(errno));
466: } else {
467: if (close(c->rfd) < 0)
468: log("channel %d: chan_shutdown_read: close() failed for fd%d: %.100s",
469: c->self, c->rfd, strerror(errno));
470: c->rfd = -1;
471: }
1.1 markus 472: }