11305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* $OpenBSD: nchan.c,v 1.63 2010/01/26 01:28:35 djm Exp $ */
21305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
31305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl.  All rights reserved.
41305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
51305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Redistribution and use in source and binary forms, with or without
61305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * modification, are permitted provided that the following conditions
71305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * are met:
81305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 1. Redistributions of source code must retain the above copyright
91305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    notice, this list of conditions and the following disclaimer.
101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 2. Redistributions in binary form must reproduce the above copyright
111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    notice, this list of conditions and the following disclaimer in the
121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    documentation and/or other materials provided with the distribution.
131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "includes.h"
271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/types.h>
291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/socket.h>
301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <errno.h>
321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <string.h>
331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdarg.h>
341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "openbsd-compat/sys-queue.h"
361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "ssh1.h"
371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "ssh2.h"
381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "buffer.h"
391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "packet.h"
401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "channels.h"
411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "compat.h"
421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "log.h"
431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * SSH Protocol 1.5 aka New Channel Protocol
461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Thanks to Martina, Axel and everyone who left Erlangen, leaving me bored.
471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Written by Markus Friedl in October 1999
481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Protocol versions 1.3 and 1.5 differ in the handshake protocol used for the
501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * tear down of channels:
511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 1.3:	strict request-ack-protocol:
531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *	CLOSE	->
541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *		<-  CLOSE_CONFIRM
551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 1.5:	uses variations of:
571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *	IEOF	->
581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *		<-  OCLOSE
591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *		<-  IEOF
601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *	OCLOSE	->
611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *	i.e. both sides have to close the channel
621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 2.0: the EOF messages are optional
641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * See the debugging output from 'ssh -v' and 'sshd -d' of
661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * ssh-1.2.27 as an example.
671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* functions manipulating channel states */
711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * EVENTS update channel input/output states execute ACTIONS
731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * ACTIONS: should never update the channel states
761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void	chan_send_ieof1(Channel *);
781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void	chan_send_oclose1(Channel *);
791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void	chan_send_close2(Channel *);
801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void	chan_send_eof2(Channel *);
811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void	chan_send_eow2(Channel *);
821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* helper */
841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void	chan_shutdown_write(Channel *);
851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void	chan_shutdown_read(Channel *);
861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic char *ostates[] = { "open", "drain", "wait_ieof", "closed" };
881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic char *istates[] = { "open", "drain", "wait_oclose", "closed" };
891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchan_set_istate(Channel *c, u_int next)
921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (c->istate > CHAN_INPUT_CLOSED || next > CHAN_INPUT_CLOSED)
941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("chan_set_istate: bad state %d -> %d", c->istate, next);
951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("channel %d: input %s -> %s", c->self, istates[c->istate],
961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    istates[next]);
971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	c->istate = next;
981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
1001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchan_set_ostate(Channel *c, u_int next)
1011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (c->ostate > CHAN_OUTPUT_CLOSED || next > CHAN_OUTPUT_CLOSED)
1031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("chan_set_ostate: bad state %d -> %d", c->ostate, next);
1041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("channel %d: output %s -> %s", c->self, ostates[c->ostate],
1051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    ostates[next]);
1061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	c->ostate = next;
1071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
1101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * SSH1 specific implementation of event functions
1111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
1121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
1141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchan_rcvd_oclose1(Channel *c)
1151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("channel %d: rcvd oclose", c->self);
1171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (c->istate) {
1181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case CHAN_INPUT_WAIT_OCLOSE:
1191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_set_istate(c, CHAN_INPUT_CLOSED);
1201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
1211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case CHAN_INPUT_OPEN:
1221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_shutdown_read(c);
1231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_send_ieof1(c);
1241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_set_istate(c, CHAN_INPUT_CLOSED);
1251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
1261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case CHAN_INPUT_WAIT_DRAIN:
1271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* both local read_failed and remote write_failed  */
1281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_send_ieof1(c);
1291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_set_istate(c, CHAN_INPUT_CLOSED);
1301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
1311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
1321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("channel %d: protocol error: rcvd_oclose for istate %d",
1331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    c->self, c->istate);
1341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
1351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
1381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchan_read_failed(Channel *c)
1391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("channel %d: read failed", c->self);
1411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (c->istate) {
1421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case CHAN_INPUT_OPEN:
1431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_shutdown_read(c);
1441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_set_istate(c, CHAN_INPUT_WAIT_DRAIN);
1451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
1461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
1471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("channel %d: chan_read_failed for istate %d",
1481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    c->self, c->istate);
1491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
1501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
1531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchan_ibuf_empty(Channel *c)
1541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("channel %d: ibuf empty", c->self);
1561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (buffer_len(&c->input)) {
1571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("channel %d: chan_ibuf_empty for non empty buffer",
1581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    c->self);
1591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
1601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (c->istate) {
1621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case CHAN_INPUT_WAIT_DRAIN:
1631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (compat20) {
1641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (!(c->flags & (CHAN_CLOSE_SENT|CHAN_LOCAL)))
1651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				chan_send_eof2(c);
1661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			chan_set_istate(c, CHAN_INPUT_CLOSED);
1671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else {
1681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			chan_send_ieof1(c);
1691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			chan_set_istate(c, CHAN_INPUT_WAIT_OCLOSE);
1701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
1711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
1721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
1731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("channel %d: chan_ibuf_empty for istate %d",
1741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    c->self, c->istate);
1751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
1761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
1791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchan_rcvd_ieof1(Channel *c)
1801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("channel %d: rcvd ieof", c->self);
1821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (c->ostate) {
1831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case CHAN_OUTPUT_OPEN:
1841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
1851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
1861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case CHAN_OUTPUT_WAIT_IEOF:
1871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
1881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
1891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
1901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("channel %d: protocol error: rcvd_ieof for ostate %d",
1911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    c->self, c->ostate);
1921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
1931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
1961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchan_write_failed1(Channel *c)
1971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("channel %d: write failed", c->self);
1991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (c->ostate) {
2001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case CHAN_OUTPUT_OPEN:
2011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_shutdown_write(c);
2021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_send_oclose1(c);
2031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_set_ostate(c, CHAN_OUTPUT_WAIT_IEOF);
2041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
2051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case CHAN_OUTPUT_WAIT_DRAIN:
2061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_shutdown_write(c);
2071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_send_oclose1(c);
2081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
2091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
2101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
2111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("channel %d: chan_write_failed for ostate %d",
2121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    c->self, c->ostate);
2131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
2141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
2171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchan_obuf_empty(Channel *c)
2181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("channel %d: obuf empty", c->self);
2201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (buffer_len(&c->output)) {
2211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("channel %d: chan_obuf_empty for non empty buffer",
2221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    c->self);
2231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
2241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (c->ostate) {
2261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case CHAN_OUTPUT_WAIT_DRAIN:
2271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_shutdown_write(c);
2281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (!compat20)
2291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			chan_send_oclose1(c);
2301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
2311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
2321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
2331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("channel %d: internal error: obuf_empty for ostate %d",
2341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    c->self, c->ostate);
2351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
2361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
2391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchan_send_ieof1(Channel *c)
2401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("channel %d: send ieof", c->self);
2421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (c->istate) {
2431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case CHAN_INPUT_OPEN:
2441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case CHAN_INPUT_WAIT_DRAIN:
2451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_start(SSH_MSG_CHANNEL_INPUT_EOF);
2461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_int(c->remote_id);
2471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_send();
2481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
2491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
2501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("channel %d: cannot send ieof for istate %d",
2511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    c->self, c->istate);
2521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
2531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
2561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchan_send_oclose1(Channel *c)
2571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("channel %d: send oclose", c->self);
2591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (c->ostate) {
2601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case CHAN_OUTPUT_OPEN:
2611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case CHAN_OUTPUT_WAIT_DRAIN:
2621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_clear(&c->output);
2631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_start(SSH_MSG_CHANNEL_OUTPUT_CLOSE);
2641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_int(c->remote_id);
2651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_send();
2661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
2671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
2681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("channel %d: cannot send oclose for ostate %d",
2691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    c->self, c->ostate);
2701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
2711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
2751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * the same for SSH2
2761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
2771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
2781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchan_rcvd_close2(Channel *c)
2791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("channel %d: rcvd close", c->self);
2811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!(c->flags & CHAN_LOCAL)) {
2821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (c->flags & CHAN_CLOSE_RCVD)
2831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("channel %d: protocol error: close rcvd twice",
2841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    c->self);
2851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		c->flags |= CHAN_CLOSE_RCVD;
2861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (c->type == SSH_CHANNEL_LARVAL) {
2881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* tear down larval channels immediately */
2891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
2901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_set_istate(c, CHAN_INPUT_CLOSED);
2911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
2921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (c->ostate) {
2941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case CHAN_OUTPUT_OPEN:
2951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/*
2961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * wait until a data from the channel is consumed if a CLOSE
2971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * is received
2981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 */
2991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
3001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
3011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
3021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (c->istate) {
3031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case CHAN_INPUT_OPEN:
3041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_shutdown_read(c);
3051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_set_istate(c, CHAN_INPUT_CLOSED);
3061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
3071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case CHAN_INPUT_WAIT_DRAIN:
3081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (!(c->flags & CHAN_LOCAL))
3091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			chan_send_eof2(c);
3101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_set_istate(c, CHAN_INPUT_CLOSED);
3111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
3121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
3131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
3141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
3161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchan_rcvd_eow(Channel *c)
3171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
3181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("channel %d: rcvd eow", c->self);
3191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (c->istate) {
3201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case CHAN_INPUT_OPEN:
3211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_shutdown_read(c);
3221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_set_istate(c, CHAN_INPUT_CLOSED);
3231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
3241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
3251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
3261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
3271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchan_rcvd_eof2(Channel *c)
3281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
3291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("channel %d: rcvd eof", c->self);
3301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	c->flags |= CHAN_EOF_RCVD;
3311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (c->ostate == CHAN_OUTPUT_OPEN)
3321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
3331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
3341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
3351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchan_write_failed2(Channel *c)
3361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
3371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("channel %d: write failed", c->self);
3381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (c->ostate) {
3391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case CHAN_OUTPUT_OPEN:
3401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case CHAN_OUTPUT_WAIT_DRAIN:
3411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_shutdown_write(c);
3421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (strcmp(c->ctype, "session") == 0)
3431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			chan_send_eow2(c);
3441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
3451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
3461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
3471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("channel %d: chan_write_failed for ostate %d",
3481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    c->self, c->ostate);
3491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
3501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
3511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
3521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
3531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchan_send_eof2(Channel *c)
3541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
3551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("channel %d: send eof", c->self);
3561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (c->istate) {
3571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case CHAN_INPUT_WAIT_DRAIN:
3581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_start(SSH2_MSG_CHANNEL_EOF);
3591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_int(c->remote_id);
3601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_send();
3611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		c->flags |= CHAN_EOF_SENT;
3621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
3631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
3641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("channel %d: cannot send eof for istate %d",
3651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    c->self, c->istate);
3661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
3671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
3681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
3691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
3701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchan_send_close2(Channel *c)
3711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
3721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("channel %d: send close", c->self);
3731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (c->ostate != CHAN_OUTPUT_CLOSED ||
3741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    c->istate != CHAN_INPUT_CLOSED) {
3751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("channel %d: cannot send close for istate/ostate %d/%d",
3761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    c->self, c->istate, c->ostate);
3771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (c->flags & CHAN_CLOSE_SENT) {
3781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("channel %d: already sent close", c->self);
3791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
3801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_start(SSH2_MSG_CHANNEL_CLOSE);
3811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_put_int(c->remote_id);
3821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		packet_send();
3831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		c->flags |= CHAN_CLOSE_SENT;
3841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
3851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
3861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
3871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchan_send_eow2(Channel *c)
3881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
3891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("channel %d: send eow", c->self);
3901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (c->ostate == CHAN_OUTPUT_CLOSED) {
3911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("channel %d: must not sent eow on closed output",
3921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    c->self);
3931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
3941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
3951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!(datafellows & SSH_NEW_OPENSSH))
3961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
3971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_start(SSH2_MSG_CHANNEL_REQUEST);
3981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_int(c->remote_id);
3991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring("eow@openssh.com");
4001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_char(0);
4011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_send();
4021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
4031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* shared */
4051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
4071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchan_rcvd_ieof(Channel *c)
4081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
4091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (compat20)
4101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_rcvd_eof2(c);
4111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else
4121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_rcvd_ieof1(c);
4131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN &&
4141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    buffer_len(&c->output) == 0 &&
4151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    !CHANNEL_EFD_OUTPUT_ACTIVE(c))
4161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_obuf_empty(c);
4171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
4181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
4191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchan_rcvd_oclose(Channel *c)
4201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
4211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (compat20)
4221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_rcvd_close2(c);
4231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else
4241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_rcvd_oclose1(c);
4251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
4261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
4271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchan_write_failed(Channel *c)
4281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
4291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (compat20)
4301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_write_failed2(c);
4311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else
4321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		chan_write_failed1(c);
4331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
4341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
4361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchan_mark_dead(Channel *c)
4371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
4381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	c->type = SSH_CHANNEL_ZOMBIE;
4391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
4401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
4421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchan_is_dead(Channel *c, int do_send)
4431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
4441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (c->type == SSH_CHANNEL_ZOMBIE) {
4451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug2("channel %d: zombie", c->self);
4461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 1;
4471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (c->istate != CHAN_INPUT_CLOSED || c->ostate != CHAN_OUTPUT_CLOSED)
4491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
4501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!compat20) {
4511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug2("channel %d: is dead", c->self);
4521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 1;
4531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((datafellows & SSH_BUG_EXTEOF) &&
4551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    c->extended_usage == CHAN_EXTENDED_WRITE &&
4561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    c->efd != -1 &&
4571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    buffer_len(&c->extended) > 0) {
4581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug2("channel %d: active efd: %d len %d",
4591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    c->self, c->efd, buffer_len(&c->extended));
4601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
4611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (c->flags & CHAN_LOCAL) {
4631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug2("channel %d: is dead (local)", c->self);
4641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 1;
4651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!(c->flags & CHAN_CLOSE_SENT)) {
4671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (do_send) {
4681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			chan_send_close2(c);
4691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else {
4701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* channel would be dead if we sent a close */
4711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (c->flags & CHAN_CLOSE_RCVD) {
4721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				debug2("channel %d: almost dead",
4731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    c->self);
4741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				return 1;
4751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
4761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
4771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((c->flags & CHAN_CLOSE_SENT) &&
4791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (c->flags & CHAN_CLOSE_RCVD)) {
4801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug2("channel %d: is dead", c->self);
4811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 1;
4821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 0;
4841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
4851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* helper */
4871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
4881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchan_shutdown_write(Channel *c)
4891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
4901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_clear(&c->output);
4911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (compat20 && c->type == SSH_CHANNEL_LARVAL)
4921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
4931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* shutdown failure is allowed if write failed already */
4941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("channel %d: close_write", c->self);
4951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (c->sock != -1) {
4961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (shutdown(c->sock, SHUT_WR) < 0)
4971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug2("channel %d: chan_shutdown_write: "
4981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    "shutdown() failed for fd %d: %.100s",
4991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    c->self, c->sock, strerror(errno));
5001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
5011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (channel_close_fd(&c->wfd) < 0)
5021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			logit("channel %d: chan_shutdown_write: "
5031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    "close() failed for fd %d: %.100s",
5041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    c->self, c->wfd, strerror(errno));
5051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
5061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
5071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
5081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodchan_shutdown_read(Channel *c)
5091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
5101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (compat20 && c->type == SSH_CHANNEL_LARVAL)
5111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return;
5121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug2("channel %d: close_read", c->self);
5131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (c->sock != -1) {
5141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/*
5151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * shutdown(sock, SHUT_READ) may return ENOTCONN if the
5161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * write side has been closed already. (bug on Linux)
5171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * HP-UX may return ENOTCONN also.
5181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 */
5191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (shutdown(c->sock, SHUT_RD) < 0
5201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    && errno != ENOTCONN)
5211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("channel %d: chan_shutdown_read: "
5221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    "shutdown() failed for fd %d [i%d o%d]: %.100s",
5231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    c->self, c->sock, c->istate, c->ostate,
5241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    strerror(errno));
5251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
5261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (channel_close_fd(&c->rfd) < 0)
5271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			logit("channel %d: chan_shutdown_read: "
5281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    "close() failed for fd %d: %.100s",
5291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    c->self, c->rfd, strerror(errno));
5301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
5311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
532