[BACK]Return to nchan.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Annotation of src/usr.bin/ssh/nchan.c, Revision 1.17.2.2

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.17.2.2! jason      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: {
                    256:        if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {
                    257:                debug("channel %d: full closed", c->self);
                    258:                channel_free(c->self);
                    259:        }
                    260: }
1.6       markus    261:
1.13      markus    262: /*
                    263:  * the same for SSH2
                    264:  */
                    265: static void
                    266: chan_rcvd_oclose2(Channel *c)
                    267: {
                    268:        debug("channel %d: rcvd close", c->self);
                    269:        if (c->flags & CHAN_CLOSE_RCVD)
                    270:                error("channel %d: protocol error: close rcvd twice", c->self);
                    271:        c->flags |= CHAN_CLOSE_RCVD;
                    272:        if (c->type == SSH_CHANNEL_LARVAL) {
                    273:                /* tear down larval channels immediately */
                    274:                c->ostate = CHAN_OUTPUT_CLOSED;
                    275:                c->istate = CHAN_INPUT_CLOSED;
                    276:                return;
                    277:        }
                    278:        switch (c->ostate) {
                    279:        case CHAN_OUTPUT_OPEN:
                    280:                /* wait until a data from the channel is consumed if a CLOSE is received */
                    281:                debug("channel %d: output open -> drain", c->self);
                    282:                c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
                    283:                break;
                    284:        }
                    285:        switch (c->istate) {
                    286:        case CHAN_INPUT_OPEN:
                    287:                debug("channel %d: input open -> closed", c->self);
                    288:                chan_shutdown_read(c);
                    289:                break;
                    290:        case CHAN_INPUT_WAIT_DRAIN:
                    291:                debug("channel %d: input drain -> closed", c->self);
                    292:                chan_send_eof2(c);
                    293:                break;
                    294:        }
                    295:        c->istate = CHAN_INPUT_CLOSED;
                    296: }
                    297: static void
                    298: chan_ibuf_empty2(Channel *c)
                    299: {
                    300:        debug("channel %d: ibuf empty", c->self);
                    301:        if (buffer_len(&c->input)) {
                    302:                error("channel %d: internal error: chan_ibuf_empty for non empty buffer",
                    303:                     c->self);
                    304:                return;
                    305:        }
                    306:        switch (c->istate) {
                    307:        case CHAN_INPUT_WAIT_DRAIN:
                    308:                debug("channel %d: input drain -> closed", c->self);
                    309:                if (!(c->flags & CHAN_CLOSE_SENT))
                    310:                        chan_send_eof2(c);
                    311:                c->istate = CHAN_INPUT_CLOSED;
                    312:                break;
                    313:        default:
                    314:                error("channel %d: internal error: chan_ibuf_empty for istate %d",
                    315:                     c->self, c->istate);
                    316:                break;
                    317:        }
                    318: }
                    319: static void
                    320: chan_rcvd_ieof2(Channel *c)
                    321: {
                    322:        debug("channel %d: rcvd eof", c->self);
                    323:        if (c->ostate == CHAN_OUTPUT_OPEN) {
                    324:                debug("channel %d: output open -> drain", c->self);
                    325:                c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
                    326:        }
                    327: }
                    328: static void
                    329: chan_write_failed2(Channel *c)
                    330: {
                    331:        debug("channel %d: write failed", c->self);
                    332:        switch (c->ostate) {
                    333:        case CHAN_OUTPUT_OPEN:
                    334:                debug("channel %d: output open -> closed", c->self);
1.15      markus    335:                chan_shutdown_write(c); /* ?? */
1.13      markus    336:                c->ostate = CHAN_OUTPUT_CLOSED;
                    337:                break;
                    338:        case CHAN_OUTPUT_WAIT_DRAIN:
                    339:                debug("channel %d: output drain -> closed", c->self);
                    340:                chan_shutdown_write(c);
                    341:                c->ostate = CHAN_OUTPUT_CLOSED;
                    342:                break;
                    343:        default:
                    344:                error("channel %d: internal error: chan_write_failed for ostate %d",
                    345:                    c->self, c->ostate);
                    346:                break;
                    347:        }
                    348: }
                    349: static void
                    350: chan_obuf_empty2(Channel *c)
                    351: {
                    352:        debug("channel %d: obuf empty", c->self);
                    353:        if (buffer_len(&c->output)) {
                    354:                error("internal error: chan_obuf_empty %d for non empty buffer",
                    355:                    c->self);
                    356:                return;
                    357:        }
                    358:        switch (c->ostate) {
                    359:        case CHAN_OUTPUT_WAIT_DRAIN:
                    360:                debug("channel %d: output drain -> closed", c->self);
                    361:                chan_shutdown_write(c);
                    362:                c->ostate = CHAN_OUTPUT_CLOSED;
                    363:                break;
                    364:        default:
                    365:                error("channel %d: internal error: chan_obuf_empty for ostate %d",
                    366:                    c->self, c->ostate);
                    367:                break;
                    368:        }
                    369: }
1.3       markus    370: static void
1.13      markus    371: chan_send_eof2(Channel *c)
1.6       markus    372: {
1.13      markus    373:        debug("channel %d: send eof", c->self);
                    374:        switch (c->istate) {
                    375:        case CHAN_INPUT_WAIT_DRAIN:
                    376:                packet_start(SSH2_MSG_CHANNEL_EOF);
                    377:                packet_put_int(c->remote_id);
                    378:                packet_send();
                    379:                break;
                    380:        default:
                    381:                error("channel %d: internal error: cannot send eof for istate %d",
                    382:                    c->self, c->istate);
                    383:                break;
                    384:        }
1.1       markus    385: }
1.3       markus    386: static void
1.13      markus    387: chan_send_close2(Channel *c)
1.6       markus    388: {
1.13      markus    389:        debug("channel %d: send close", c->self);
                    390:        if (c->ostate != CHAN_OUTPUT_CLOSED ||
                    391:            c->istate != CHAN_INPUT_CLOSED) {
                    392:                error("channel %d: internal error: cannot send close for istate/ostate %d/%d",
                    393:                    c->self, c->istate, c->ostate);
                    394:        } else if (c->flags & CHAN_CLOSE_SENT) {
                    395:                error("channel %d: internal error: already sent close", c->self);
                    396:        } else {
                    397:                packet_start(SSH2_MSG_CHANNEL_CLOSE);
                    398:                packet_put_int(c->remote_id);
                    399:                packet_send();
                    400:                c->flags |= CHAN_CLOSE_SENT;
                    401:        }
1.1       markus    402: }
1.13      markus    403: static void
                    404: chan_delete_if_full_closed2(Channel *c)
1.6       markus    405: {
                    406:        if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {
1.13      markus    407:                if (!(c->flags & CHAN_CLOSE_SENT)) {
                    408:                        chan_send_close2(c);
                    409:                }
1.14      markus    410:                if ((c->flags & CHAN_CLOSE_SENT) &&
1.13      markus    411:                    (c->flags & CHAN_CLOSE_RCVD)) {
                    412:                        debug("channel %d: full closed2", c->self);
                    413:                        channel_free(c->self);
1.14      markus    414:                }
1.1       markus    415:        }
1.3       markus    416: }
1.13      markus    417:
                    418: /* shared */
1.3       markus    419: void
1.6       markus    420: chan_init_iostates(Channel *c)
                    421: {
                    422:        c->ostate = CHAN_OUTPUT_OPEN;
                    423:        c->istate = CHAN_INPUT_OPEN;
1.13      markus    424:        c->flags = 0;
                    425: }
                    426:
                    427: /* init */
                    428: void
                    429: chan_init(void)
                    430: {
                    431:        if (compat20) {
                    432:                chan_rcvd_oclose                = chan_rcvd_oclose2;
                    433:                chan_read_failed                = chan_read_failed_12;
                    434:                chan_ibuf_empty                 = chan_ibuf_empty2;
                    435:
                    436:                chan_rcvd_ieof                  = chan_rcvd_ieof2;
                    437:                chan_write_failed               = chan_write_failed2;
                    438:                chan_obuf_empty                 = chan_obuf_empty2;
                    439:
                    440:                chan_delete_if_full_closed      = chan_delete_if_full_closed2;
                    441:        } else {
                    442:                chan_rcvd_oclose                = chan_rcvd_oclose1;
                    443:                chan_read_failed                = chan_read_failed_12;
                    444:                chan_ibuf_empty                 = chan_ibuf_empty1;
                    445:
                    446:                chan_rcvd_ieof                  = chan_rcvd_ieof1;
                    447:                chan_write_failed               = chan_write_failed1;
                    448:                chan_obuf_empty                 = chan_obuf_empty1;
                    449:
                    450:                chan_delete_if_full_closed      = chan_delete_if_full_closed1;
                    451:        }
                    452: }
                    453:
                    454: /* helper */
                    455: static void
                    456: chan_shutdown_write(Channel *c)
                    457: {
                    458:        buffer_consume(&c->output, buffer_len(&c->output));
                    459:        if (compat20 && c->type == SSH_CHANNEL_LARVAL)
                    460:                return;
                    461:        /* shutdown failure is allowed if write failed already */
                    462:        debug("channel %d: close_write", c->self);
                    463:        if (c->sock != -1) {
                    464:                if (shutdown(c->sock, SHUT_WR) < 0)
                    465:                        debug("channel %d: chan_shutdown_write: shutdown() failed for fd%d: %.100s",
                    466:                            c->self, c->sock, strerror(errno));
                    467:        } else {
                    468:                if (close(c->wfd) < 0)
                    469:                        log("channel %d: chan_shutdown_write: close() failed for fd%d: %.100s",
                    470:                            c->self, c->wfd, strerror(errno));
                    471:                c->wfd = -1;
                    472:        }
                    473: }
                    474: static void
                    475: chan_shutdown_read(Channel *c)
                    476: {
                    477:        if (compat20 && c->type == SSH_CHANNEL_LARVAL)
                    478:                return;
                    479:        debug("channel %d: close_read", c->self);
                    480:        if (c->sock != -1) {
                    481:                if (shutdown(c->sock, SHUT_RD) < 0)
                    482:                        error("channel %d: chan_shutdown_read: shutdown() failed for fd%d [i%d o%d]: %.100s",
                    483:                            c->self, c->sock, c->istate, c->ostate, strerror(errno));
                    484:        } else {
                    485:                if (close(c->rfd) < 0)
                    486:                        log("channel %d: chan_shutdown_read: close() failed for fd%d: %.100s",
                    487:                            c->self, c->rfd, strerror(errno));
                    488:                c->rfd = -1;
                    489:        }
1.1       markus    490: }