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

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