[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.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: }