[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.24

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