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

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