1f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/*
2f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Dropbear SSH
3f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
4f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Copyright (c) 2002-2004 Matt Johnston
5f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * All rights reserved.
6f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
7f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Permission is hereby granted, free of charge, to any person obtaining a copy
8f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * of this software and associated documentation files (the "Software"), to deal
9f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * in the Software without restriction, including without limitation the rights
10f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * copies of the Software, and to permit persons to whom the Software is
12f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * furnished to do so, subject to the following conditions:
13f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
14f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * The above copyright notice and this permission notice shall be included in
15f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * all copies or substantial portions of the Software.
16f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
17f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * SOFTWARE. */
24f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
25f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Handle the multiplexed channels, such as sessions, x11, agent connections */
26f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
27f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "includes.h"
28f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "session.h"
29f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "packet.h"
30f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "ssh.h"
31f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "buffer.h"
32f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "circbuffer.h"
33f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "dbutil.h"
34f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "channel.h"
35f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "ssh.h"
36f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "listener.h"
37f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
38f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void send_msg_channel_open_failure(unsigned int remotechan, int reason,
39f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		const unsigned char *text, const unsigned char *lang);
40f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void send_msg_channel_open_confirmation(struct Channel* channel,
41f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		unsigned int recvwindow,
42f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		unsigned int recvmaxpacket);
43f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void writechannel(struct Channel* channel, int fd, circbuffer *cbuf);
44f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void send_msg_channel_window_adjust(struct Channel *channel,
45f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		unsigned int incr);
46f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void send_msg_channel_data(struct Channel *channel, int isextended);
47f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void send_msg_channel_eof(struct Channel *channel);
48f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void send_msg_channel_close(struct Channel *channel);
49f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void remove_channel(struct Channel *channel);
50f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void delete_channel(struct Channel *channel);
51f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void check_in_progress(struct Channel *channel);
52f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic unsigned int write_pending(struct Channel * channel);
53f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void check_close(struct Channel *channel);
54f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void close_chan_fd(struct Channel *channel, int fd, int how);
55f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
56f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define FD_UNINIT (-2)
57f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define FD_CLOSED (-1)
58f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
59f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define ERRFD_IS_READ(channel) ((channel)->extrabuf == NULL)
60f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define ERRFD_IS_WRITE(channel) (!ERRFD_IS_READ(channel))
61f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
62f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Initialise all the channels */
63f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid chaninitialise(const struct ChanType *chantypes[]) {
64f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
65f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* may as well create space for a single channel */
66f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.channels = (struct Channel**)m_malloc(sizeof(struct Channel*));
67f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.chansize = 1;
68f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.channels[0] = NULL;
69f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.chancount = 0;
70f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
71f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.chantypes = chantypes;
72f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
73f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef USING_LISTENERS
74f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	listeners_initialise();
75f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
76f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
77f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
78f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
79f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Clean up channels, freeing allocated memory */
80f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid chancleanup() {
81f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
82f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned int i;
83f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
84f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("enter chancleanup"))
85f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	for (i = 0; i < ses.chansize; i++) {
86f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (ses.channels[i] != NULL) {
87f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			TRACE(("channel %d closing", i))
88f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			remove_channel(ses.channels[i]);
89f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
90f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
91f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	m_free(ses.channels);
92f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("leave chancleanup"))
93f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
94f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
95f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Create a new channel entry, send a reply confirm or failure */
96f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* If remotechan, transwindow and transmaxpacket are not know (for a new
97f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * outgoing connection, with them to be filled on confirmation), they should
98f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * all be set to 0 */
99f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstruct Channel* newchannel(unsigned int remotechan,
100f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		const struct ChanType *type,
101f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		unsigned int transwindow, unsigned int transmaxpacket) {
102f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
103f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	struct Channel * newchan;
104f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned int i, j;
105f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
106f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("enter newchannel"))
107f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
108f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* first see if we can use existing channels */
109f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	for (i = 0; i < ses.chansize; i++) {
110f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (ses.channels[i] == NULL) {
111f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			break;
112f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
113f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
114f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
115f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* otherwise extend the list */
116f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (i == ses.chansize) {
117f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (ses.chansize >= MAX_CHANNELS) {
118f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			TRACE(("leave newchannel: max chans reached"))
119f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			return NULL;
120f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
121f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
122f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		/* extend the channels */
123f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		ses.channels = (struct Channel**)m_realloc(ses.channels,
124f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				(ses.chansize+CHAN_EXTEND_SIZE)*sizeof(struct Channel*));
125f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
126f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		ses.chansize += CHAN_EXTEND_SIZE;
127f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
128f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		/* set the new channels to null */
129f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		for (j = i; j < ses.chansize; j++) {
130f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			ses.channels[j] = NULL;
131f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
132f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
133f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
134f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
135f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	newchan = (struct Channel*)m_malloc(sizeof(struct Channel));
136f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	newchan->type = type;
137f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	newchan->index = i;
138f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	newchan->sent_close = newchan->recv_close = 0;
139f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	newchan->sent_eof = newchan->recv_eof = 0;
140f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
141f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	newchan->remotechan = remotechan;
142f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	newchan->transwindow = transwindow;
143f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	newchan->transmaxpacket = transmaxpacket;
144f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
145f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	newchan->typedata = NULL;
146f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	newchan->writefd = FD_UNINIT;
147f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	newchan->readfd = FD_UNINIT;
148f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	newchan->errfd = FD_CLOSED; /* this isn't always set to start with */
149f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	newchan->initconn = 0;
150f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	newchan->await_open = 0;
151f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	newchan->flushing = 0;
152f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
153f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	newchan->writebuf = cbuf_new(RECV_MAXWINDOW);
154f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	newchan->extrabuf = NULL; /* The user code can set it up */
155f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	newchan->recvwindow = RECV_MAXWINDOW;
156f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	newchan->recvdonelen = 0;
157f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	newchan->recvmaxpacket = RECV_MAXPACKET;
158f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
159f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.channels[i] = newchan;
160f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.chancount++;
161f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
162f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("leave newchannel"))
163f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
164f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	return newchan;
165f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
166f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
167f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Returns the channel structure corresponding to the channel in the current
168f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * data packet (ses.payload must be positioned appropriately).
169f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * A valid channel is always returns, it will fail fatally with an unknown
170f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * channel */
171f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic struct Channel* getchannel_msg(const char* kind) {
172f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
173f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned int chan;
174f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
175f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	chan = buf_getint(ses.payload);
176f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (chan >= ses.chansize || ses.channels[chan] == NULL) {
177f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (kind) {
178f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			dropbear_exit("%s for unknown channel %d", kind, chan);
179f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		} else {
180f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			dropbear_exit("Unknown channel %d", chan);
181f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
182f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
183f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	return ses.channels[chan];
184f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
185f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
186f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstruct Channel* getchannel() {
187f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	return getchannel_msg(NULL);
188f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
189f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
190f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Iterate through the channels, performing IO if available */
191f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid channelio(fd_set *readfds, fd_set *writefds) {
192f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
193f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	struct Channel *channel;
194f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned int i;
195f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
196f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* foreach channel */
197f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	for (i = 0; i < ses.chansize; i++) {
198f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
199f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		channel = ses.channels[i];
200f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (channel == NULL) {
201f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			/* only process in-use channels */
202f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			continue;
203f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
204f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
205f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		/* read data and send it over the wire */
206f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (channel->readfd >= 0 && FD_ISSET(channel->readfd, readfds)) {
207f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			TRACE(("send normal readfd"))
208f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			send_msg_channel_data(channel, 0);
209f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
210f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
211f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		/* read stderr data and send it over the wire */
212f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (ERRFD_IS_READ(channel) && channel->errfd >= 0
213f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			&& FD_ISSET(channel->errfd, readfds)) {
214f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				TRACE(("send normal errfd"))
215f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				send_msg_channel_data(channel, 1);
216f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
217f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
218f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		/* write to program/pipe stdin */
219f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (channel->writefd >= 0 && FD_ISSET(channel->writefd, writefds)) {
220f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			if (channel->initconn) {
221f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				/* XXX should this go somewhere cleaner? */
222f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				check_in_progress(channel);
223f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				continue; /* Important not to use the channel after
224f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project							 check_in_progress(), as it may be NULL */
225f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			}
226f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			writechannel(channel, channel->writefd, channel->writebuf);
227f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
228f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
229f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		/* stderr for client mode */
230f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (ERRFD_IS_WRITE(channel)
231f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				&& channel->errfd >= 0 && FD_ISSET(channel->errfd, writefds)) {
232f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			writechannel(channel, channel->errfd, channel->extrabuf);
233f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
234f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
235f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		/* handle any channel closing etc */
236f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		check_close(channel);
237f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
238f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
239f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
240f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* Listeners such as TCP, X11, agent-auth */
241f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef USING_LISTENERS
242f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	handle_listeners(readfds);
243f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
244f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
245f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
246f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
247f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Returns true if there is data remaining to be written to stdin or
248f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * stderr of a channel's endpoint. */
249f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic unsigned int write_pending(struct Channel * channel) {
250f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
251f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0) {
252f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		return 1;
253f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	} else if (channel->errfd >= 0 && channel->extrabuf &&
254f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			cbuf_getused(channel->extrabuf) > 0) {
255f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		return 1;
256f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
257f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	return 0;
258f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
259f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
260f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
261f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* EOF/close handling */
262f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void check_close(struct Channel *channel) {
263f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
264f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("check_close: writefd %d, readfd %d, errfd %d, sent_close %d, recv_close %d",
265f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				channel->writefd, channel->readfd,
266f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				channel->errfd, channel->sent_close, channel->recv_close))
267f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("writebuf size %d extrabuf size %d",
268f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				cbuf_getused(channel->writebuf),
269f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				channel->extrabuf ? cbuf_getused(channel->extrabuf) : 0))
270f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
271f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (!channel->flushing && channel->type->check_close
272f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		&& channel->type->check_close(channel))
273f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	{
274f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		channel->flushing = 1;
275f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
276f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
277f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (channel->recv_close && !write_pending(channel)) {
278f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (!channel->sent_close) {
279f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			TRACE(("Sending MSG_CHANNEL_CLOSE in response to same."))
280f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			send_msg_channel_close(channel);
281f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
282f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		remove_channel(channel);
283f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		return;
284f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
285f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
286f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (channel->recv_eof && !write_pending(channel)) {
287f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		close_chan_fd(channel, channel->writefd, SHUT_WR);
288f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
289f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
290f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* Special handling for flushing read data after an exit. We
291f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	   read regardless of whether the select FD was set,
292f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	   and if there isn't data available, the channel will get closed. */
293f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (channel->flushing) {
294f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("might send data, flushing"))
295f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (channel->readfd >= 0 && channel->transwindow > 0) {
296f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			TRACE(("send data readfd"))
297f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			send_msg_channel_data(channel, 0);
298f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
299f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (ERRFD_IS_READ(channel) && channel->errfd >= 0
300f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			&& channel->transwindow > 0) {
301f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			TRACE(("send data errfd"))
302f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			send_msg_channel_data(channel, 1);
303f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
304f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
305f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
306f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* If we're not going to send any more data, send EOF */
307f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (!channel->sent_eof
308f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			&& channel->readfd == FD_CLOSED
309f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			&& (ERRFD_IS_WRITE(channel) || channel->errfd == FD_CLOSED)) {
310f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		send_msg_channel_eof(channel);
311f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
312f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
313f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* And if we can't receive any more data from them either, close up */
314f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (!channel->sent_close
315f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			&& channel->readfd == FD_CLOSED
316f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			&& (ERRFD_IS_WRITE(channel) || channel->errfd == FD_CLOSED)
317f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			&& !write_pending(channel)) {
318f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("sending close, readfd is closed"))
319f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		send_msg_channel_close(channel);
320f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
321f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
322f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
323f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Check whether a deferred (EINPROGRESS) connect() was successful, and
324f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * if so, set up the channel properly. Otherwise, the channel is cleaned up, so
325f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * it is important that the channel reference isn't used after a call to this
326f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * function */
327f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void check_in_progress(struct Channel *channel) {
328f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
329f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	int val;
330f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	socklen_t vallen = sizeof(val);
331f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
332f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("enter check_in_progress"))
333f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
334f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (getsockopt(channel->writefd, SOL_SOCKET, SO_ERROR, &val, &vallen)
335f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			|| val != 0) {
336f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		send_msg_channel_open_failure(channel->remotechan,
337f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				SSH_OPEN_CONNECT_FAILED, "", "");
338f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		close(channel->writefd);
339f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		delete_channel(channel);
340f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("leave check_in_progress: fail"))
341f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	} else {
342f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		send_msg_channel_open_confirmation(channel, channel->recvwindow,
343f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				channel->recvmaxpacket);
344f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		channel->readfd = channel->writefd;
345f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		channel->initconn = 0;
346f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("leave check_in_progress: success"))
347f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
348f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
349f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
350f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
351f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Send the close message and set the channel as closed */
352f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void send_msg_channel_close(struct Channel *channel) {
353f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
354f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("enter send_msg_channel_close"))
355f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (channel->type->closehandler) {
356f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		channel->type->closehandler(channel);
357f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
358f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
359f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	CHECKCLEARTOWRITE();
360f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
361f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_CLOSE);
362f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putint(ses.writepayload, channel->remotechan);
363f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
364f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	encrypt_packet();
365f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
366f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	channel->sent_eof = 1;
367f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	channel->sent_close = 1;
368f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	close_chan_fd(channel, channel->readfd, SHUT_RD);
369f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	close_chan_fd(channel, channel->errfd, SHUT_RDWR);
370f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	close_chan_fd(channel, channel->writefd, SHUT_WR);
371f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("leave send_msg_channel_close"))
372f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
373f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
374f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* call this when trans/eof channels are closed */
375f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void send_msg_channel_eof(struct Channel *channel) {
376f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
377f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("enter send_msg_channel_eof"))
378f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	CHECKCLEARTOWRITE();
379f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
380f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_EOF);
381f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putint(ses.writepayload, channel->remotechan);
382f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
383f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	encrypt_packet();
384f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
385f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	channel->sent_eof = 1;
386f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
387f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("leave send_msg_channel_eof"))
388f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
389f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
390f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Called to write data out to the local side of the channel.
391f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Only called when we know we can write to a channel, writes as much as
392f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * possible */
393f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void writechannel(struct Channel* channel, int fd, circbuffer *cbuf) {
394f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
395f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	int len, maxlen;
396f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
397f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("enter writechannel fd %d", fd))
398f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
399f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	maxlen = cbuf_readlen(cbuf);
400f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
401f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* Write the data out */
402f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	len = write(fd, cbuf_readptr(cbuf, maxlen), maxlen);
403f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (len <= 0) {
404f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("errno %d len %d", errno, len))
405f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (len < 0 && errno != EINTR) {
406f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			close_chan_fd(channel, fd, SHUT_WR);
407f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
408f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("leave writechannel: len <= 0"))
409f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		return;
410f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
411f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("writechannel wrote %d", len))
412f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
413f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	cbuf_incrread(cbuf, len);
414f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	channel->recvdonelen += len;
415f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
416f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* Window adjust handling */
417f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (channel->recvdonelen >= RECV_WINDOWEXTEND) {
418f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		/* Set it back to max window */
419f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		send_msg_channel_window_adjust(channel, channel->recvdonelen);
420f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		channel->recvwindow += channel->recvdonelen;
421f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		channel->recvdonelen = 0;
422f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
423f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
424f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	dropbear_assert(channel->recvwindow <= RECV_MAXWINDOW);
425f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	dropbear_assert(channel->recvwindow <= cbuf_getavail(channel->writebuf));
426f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	dropbear_assert(channel->extrabuf == NULL ||
427f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			channel->recvwindow <= cbuf_getavail(channel->extrabuf));
428f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
429f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("leave writechannel"))
430f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
431f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
432f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Set the file descriptors for the main select in session.c
433f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * This avoid channels which don't have any window available, are closed, etc*/
434f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid setchannelfds(fd_set *readfds, fd_set *writefds) {
435f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
436f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned int i;
437f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	struct Channel * channel;
438f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
439f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	for (i = 0; i < ses.chansize; i++) {
440f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
441f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		channel = ses.channels[i];
442f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (channel == NULL) {
443f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			continue;
444f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
445f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
446f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		/* Stuff to put over the wire */
447f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (channel->transwindow > 0) {
448f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
449f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			if (channel->readfd >= 0) {
450f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				FD_SET(channel->readfd, readfds);
451f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			}
452f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
453f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			if (ERRFD_IS_READ(channel) && channel->errfd >= 0) {
454f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project					FD_SET(channel->errfd, readfds);
455f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			}
456f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
457f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
458f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		/* Stuff from the wire */
459f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if ((channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0 )
460f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				|| channel->initconn) {
461f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				FD_SET(channel->writefd, writefds);
462f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
463f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
464f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (ERRFD_IS_WRITE(channel) && channel->errfd >= 0
465f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				&& cbuf_getused(channel->extrabuf) > 0 ) {
466f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				FD_SET(channel->errfd, writefds);
467f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
468f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
469f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	} /* foreach channel */
470f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
471f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef USING_LISTENERS
472f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	set_listener_fds(readfds);
473f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
474f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
475f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
476f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
477f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* handle the channel EOF event, by closing the channel filedescriptor. The
478f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * channel isn't closed yet, it is left until the incoming (from the program
479f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * etc) FD is also EOF */
480f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid recv_msg_channel_eof() {
481f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
482f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	struct Channel * channel;
483f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
484f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("enter recv_msg_channel_eof"))
485f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
486f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	channel = getchannel_msg("EOF");
487f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
488f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	channel->recv_eof = 1;
489f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
490f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	check_close(channel);
491f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("leave recv_msg_channel_eof"))
492f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
493f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
494f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
495f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Handle channel closure(), respond in kind and close the channels */
496f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid recv_msg_channel_close() {
497f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
498f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	struct Channel * channel;
499f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
500f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("enter recv_msg_channel_close"))
501f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
502f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	channel = getchannel_msg("Close");
503f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
504f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	channel->recv_eof = 1;
505f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	channel->recv_close = 1;
506f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
507f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	check_close(channel);
508f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("leave recv_msg_channel_close"))
509f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
510f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
511f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Remove a channel entry, this is only executed after both sides have sent
512f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * channel close */
513f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void remove_channel(struct Channel * channel) {
514f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
515f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("enter remove_channel"))
516f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("channel index is %d", channel->index))
517f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
518f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	cbuf_free(channel->writebuf);
519f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	channel->writebuf = NULL;
520f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
521f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (channel->extrabuf) {
522f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		cbuf_free(channel->extrabuf);
523f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		channel->extrabuf = NULL;
524f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
525f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
526f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
527f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* close the FDs in case they haven't been done
528f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	 * yet (they might have been shutdown etc) */
529f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("CLOSE writefd %d", channel->writefd))
530f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	close(channel->writefd);
531f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("CLOSE readfd %d", channel->readfd))
532f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	close(channel->readfd);
533f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("CLOSE errfd %d", channel->errfd))
534f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	close(channel->errfd);
535f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
536f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	channel->typedata = NULL;
537f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
538f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	delete_channel(channel);
539f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
540f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("leave remove_channel"))
541f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
542f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
543f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Remove a channel entry */
544f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void delete_channel(struct Channel *channel) {
545f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
546f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.channels[channel->index] = NULL;
547f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	m_free(channel);
548f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.chancount--;
549f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
550f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
551f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
552f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
553f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Handle channel specific requests, passing off to corresponding handlers
554f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * such as chansession or x11fwd */
555f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid recv_msg_channel_request() {
556f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
557f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	struct Channel *channel;
558f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
559f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("enter recv_msg_channel_request"))
560f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
561f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	channel = getchannel();
562f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
563f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (channel->type->reqhandler) {
564f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		channel->type->reqhandler(channel);
565f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	} else {
566f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		send_msg_channel_failure(channel);
567f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
568f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
569f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("leave recv_msg_channel_request"))
570f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
571f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
572f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
573f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Reads data from the server's program/shell/etc, and puts it in a
574f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * channel_data packet to send.
575f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * chan is the remote channel, isextended is 0 if it is normal data, 1
576f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * if it is extended data. if it is extended, then the type is in
577f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * exttype */
578f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void send_msg_channel_data(struct Channel *channel, int isextended) {
579f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
580f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	int len;
581f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	size_t maxlen, size_pos;
582f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	int fd;
583f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
584f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	CHECKCLEARTOWRITE();
585f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
586f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("enter send_msg_channel_data"))
587f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	dropbear_assert(!channel->sent_close);
588f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
589f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (isextended) {
590f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		fd = channel->errfd;
591f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	} else {
592f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		fd = channel->readfd;
593f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
594f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("enter send_msg_channel_data isextended %d fd %d", isextended, fd))
595f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	dropbear_assert(fd >= 0);
596f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
597f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	maxlen = MIN(channel->transwindow, channel->transmaxpacket);
598f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* -(1+4+4) is SSH_MSG_CHANNEL_DATA, channel number, string length, and
599f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	 * exttype if is extended */
600f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	maxlen = MIN(maxlen,
601f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			ses.writepayload->size - 1 - 4 - 4 - (isextended ? 4 : 0));
602f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("maxlen %d", maxlen))
603f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (maxlen == 0) {
604f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("leave send_msg_channel_data: no window"))
605f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		return;
606f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
607f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
608f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putbyte(ses.writepayload,
609f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			isextended ? SSH_MSG_CHANNEL_EXTENDED_DATA : SSH_MSG_CHANNEL_DATA);
610f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putint(ses.writepayload, channel->remotechan);
611f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (isextended) {
612f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		buf_putint(ses.writepayload, SSH_EXTENDED_DATA_STDERR);
613f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
614f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* a dummy size first ...*/
615f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	size_pos = ses.writepayload->pos;
616f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putint(ses.writepayload, 0);
617f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
618f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* read the data */
619f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	len = read(fd, buf_getwriteptr(ses.writepayload, maxlen), maxlen);
620f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (len <= 0) {
621f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (len == 0 || errno != EINTR) {
622f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			/* This will also get hit in the case of EAGAIN. The only
623f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			time we expect to receive EAGAIN is when we're flushing a FD,
624f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			in which case it can be treated the same as EOF */
625f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			close_chan_fd(channel, fd, SHUT_RD);
626f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
627f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		ses.writepayload->len = ses.writepayload->pos = 0;
628f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("leave send_msg_channel_data: len %d read err %d or EOF for fd %d",
629f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project					len, errno, fd))
630f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		return;
631f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
632f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_incrwritepos(ses.writepayload, len);
633f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* ... real size here */
634f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_setpos(ses.writepayload, size_pos);
635f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putint(ses.writepayload, len);
636f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
637f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	channel->transwindow -= len;
638f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
639f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	encrypt_packet();
640f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
641f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* If we receive less data than we requested when flushing, we've
642f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	   reached the equivalent of EOF */
643f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (channel->flushing && len < (ssize_t)maxlen)
644f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	{
645f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("closing from channel, flushing out."))
646f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		close_chan_fd(channel, fd, SHUT_RD);
647f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
648f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("leave send_msg_channel_data"))
649f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
650f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
651f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* We receive channel data */
652f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid recv_msg_channel_data() {
653f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
654f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	struct Channel *channel;
655f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
656f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	channel = getchannel();
657f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
658f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	common_recv_msg_channel_data(channel, channel->writefd, channel->writebuf);
659f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
660f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
661f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Shared for data and stderr data - when we receive data, put it in a buffer
662f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * for writing to the local file descriptor */
663f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid common_recv_msg_channel_data(struct Channel *channel, int fd,
664f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		circbuffer * cbuf) {
665f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
666f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned int datalen;
667f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned int maxdata;
668f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned int buflen;
669f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned int len;
670f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
671f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("enter recv_msg_channel_data"))
672f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
673f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (channel->recv_eof) {
674f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		dropbear_exit("received data after eof");
675f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
676f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
677f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 	if (fd < 0) {
678f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		/* If we have encountered failed write, the far side might still
679f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		 * be sending data without having yet received our close notification.
680f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		 * We just drop the data. */
681f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		return;
682f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
683f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
684f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	datalen = buf_getint(ses.payload);
685f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("length %d", datalen))
686f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
687f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	maxdata = cbuf_getavail(cbuf);
688f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
689f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* Whilst the spec says we "MAY ignore data past the end" this could
690f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	 * lead to corrupted file transfers etc (chunks missed etc). It's better to
691f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	 * just die horribly */
692f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (datalen > maxdata) {
693f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		dropbear_exit("Oversized packet");
694f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
695f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
696f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* We may have to run throught twice, if the buffer wraps around. Can't
697f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	 * just "leave it for next time" like with writechannel, since this
698f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	 * is payload data */
699f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	len = datalen;
700f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	while (len > 0) {
701f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		buflen = cbuf_writelen(cbuf);
702f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		buflen = MIN(buflen, len);
703f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
704f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		memcpy(cbuf_writeptr(cbuf, buflen),
705f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				buf_getptr(ses.payload, buflen), buflen);
706f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		cbuf_incrwrite(cbuf, buflen);
707f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		buf_incrpos(ses.payload, buflen);
708f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		len -= buflen;
709f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
710f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
711f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	dropbear_assert(channel->recvwindow >= datalen);
712f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	channel->recvwindow -= datalen;
713f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	dropbear_assert(channel->recvwindow <= RECV_MAXWINDOW);
714f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
715f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("leave recv_msg_channel_data"))
716f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
717f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
718f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Increment the outgoing data window for a channel - the remote end limits
719f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * the amount of data which may be transmitted, this window is decremented
720f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * as data is sent, and incremented upon receiving window-adjust messages */
721f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid recv_msg_channel_window_adjust() {
722f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
723f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	struct Channel * channel;
724f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned int incr;
725f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
726f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	channel = getchannel();
727f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
728f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	incr = buf_getint(ses.payload);
729f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("received window increment %d", incr))
730f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	incr = MIN(incr, MAX_TRANS_WIN_INCR);
731f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
732f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	channel->transwindow += incr;
733f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	channel->transwindow = MIN(channel->transwindow, MAX_TRANS_WINDOW);
734f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
735f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
736f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
737f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Increment the incoming data window for a channel, and let the remote
738f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * end know */
739f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void send_msg_channel_window_adjust(struct Channel* channel,
740f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		unsigned int incr) {
741f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
742f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("sending window adjust %d", incr))
743f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	CHECKCLEARTOWRITE();
744f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
745f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_WINDOW_ADJUST);
746f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putint(ses.writepayload, channel->remotechan);
747f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putint(ses.writepayload, incr);
748f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
749f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	encrypt_packet();
750f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
751f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
752f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Handle a new channel request, performing any channel-type-specific setup */
753f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid recv_msg_channel_open() {
754f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
755f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned char *type;
756f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned int typelen;
757f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned int remotechan, transwindow, transmaxpacket;
758f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	struct Channel *channel;
759f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	const struct ChanType **cp;
760f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	const struct ChanType *chantype;
761f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	unsigned int errtype = SSH_OPEN_UNKNOWN_CHANNEL_TYPE;
762f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	int ret;
763f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
764f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
765f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("enter recv_msg_channel_open"))
766f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
767f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* get the packet contents */
768f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	type = buf_getstring(ses.payload, &typelen);
769f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
770f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	remotechan = buf_getint(ses.payload);
771f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	transwindow = buf_getint(ses.payload);
772f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	transwindow = MIN(transwindow, MAX_TRANS_WINDOW);
773f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	transmaxpacket = buf_getint(ses.payload);
774f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	transmaxpacket = MIN(transmaxpacket, MAX_TRANS_PAYLOAD_LEN);
775f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
776f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* figure what type of packet it is */
777f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (typelen > MAX_NAME_LEN) {
778f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		goto failure;
779f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
780f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
781f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* Get the channel type. Client and server style invokation will set up a
782f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	 * different list for ses.chantypes at startup. We just iterate through
783f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	 * this list and find the matching name */
784f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	for (cp = &ses.chantypes[0], chantype = (*cp);
785f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			chantype != NULL;
786f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			cp++, chantype = (*cp)) {
787f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (strcmp(type, chantype->name) == 0) {
788f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			break;
789f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
790f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
791f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
792f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (chantype == NULL) {
793f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("No matching type for '%s'", type))
794f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		goto failure;
795f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
796f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
797f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("matched type '%s'", type))
798f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
799f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* create the channel */
800f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	channel = newchannel(remotechan, chantype, transwindow, transmaxpacket);
801f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
802f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (channel == NULL) {
803f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("newchannel returned NULL"))
804f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		goto failure;
805f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
806f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
807f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (channel->type->inithandler) {
808f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		ret = channel->type->inithandler(channel);
809f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (ret == SSH_OPEN_IN_PROGRESS) {
810f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			/* We'll send the confirmation later */
811f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			goto cleanup;
812f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
813f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (ret > 0) {
814f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			errtype = ret;
815f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			delete_channel(channel);
816f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			TRACE(("inithandler returned failure %d", ret))
817f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			goto failure;
818f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
819f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
820f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
821f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* success */
822f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	send_msg_channel_open_confirmation(channel, channel->recvwindow,
823f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			channel->recvmaxpacket);
824f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	goto cleanup;
825f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
826f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectfailure:
827f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("recv_msg_channel_open failure"))
828f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	send_msg_channel_open_failure(remotechan, errtype, "", "");
829f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
830f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectcleanup:
831f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	m_free(type);
832f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
833f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("leave recv_msg_channel_open"))
834f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
835f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
836f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Send a failure message */
837f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid send_msg_channel_failure(struct Channel *channel) {
838f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
839f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("enter send_msg_channel_failure"))
840f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	CHECKCLEARTOWRITE();
841f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
842f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_FAILURE);
843f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putint(ses.writepayload, channel->remotechan);
844f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
845f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	encrypt_packet();
846f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("leave send_msg_channel_failure"))
847f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
848f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
849f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Send a success message */
850f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid send_msg_channel_success(struct Channel *channel) {
851f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
852f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("enter send_msg_channel_success"))
853f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	CHECKCLEARTOWRITE();
854f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
855f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_SUCCESS);
856f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putint(ses.writepayload, channel->remotechan);
857f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
858f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	encrypt_packet();
859f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("leave send_msg_channel_success"))
860f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
861f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
862f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Send a channel open failure message, with a corresponding reason
863f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * code (usually resource shortage or unknown chan type) */
864f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void send_msg_channel_open_failure(unsigned int remotechan,
865f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		int reason, const unsigned char *text, const unsigned char *lang) {
866f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
867f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("enter send_msg_channel_open_failure"))
868f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	CHECKCLEARTOWRITE();
869f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
870f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN_FAILURE);
871f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putint(ses.writepayload, remotechan);
872f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putint(ses.writepayload, reason);
873f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putstring(ses.writepayload, text, strlen((char*)text));
874f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putstring(ses.writepayload, lang, strlen((char*)lang));
875f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
876f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	encrypt_packet();
877f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("leave send_msg_channel_open_failure"))
878f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
879f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
880f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Confirm a channel open, and let the remote end know what number we've
881f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * allocated and the receive parameters */
882f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void send_msg_channel_open_confirmation(struct Channel* channel,
883f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		unsigned int recvwindow,
884f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		unsigned int recvmaxpacket) {
885f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
886f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("enter send_msg_channel_open_confirmation"))
887f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	CHECKCLEARTOWRITE();
888f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
889f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
890f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putint(ses.writepayload, channel->remotechan);
891f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putint(ses.writepayload, channel->index);
892f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putint(ses.writepayload, recvwindow);
893f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putint(ses.writepayload, recvmaxpacket);
894f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
895f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	encrypt_packet();
896f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("leave send_msg_channel_open_confirmation"))
897f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
898f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
899f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* close a fd, how is SHUT_RD or SHUT_WR */
900f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void close_chan_fd(struct Channel *channel, int fd, int how) {
901f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
902f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	int closein = 0, closeout = 0;
903f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
904f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (channel->type->sepfds) {
905f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("SHUTDOWN(%d, %d)", fd, how))
906f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		shutdown(fd, how);
907f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (how == 0) {
908f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			closeout = 1;
909f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		} else {
910f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			closein = 1;
911f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
912f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	} else {
913f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("CLOSE some fd %d", fd))
914f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		close(fd);
915f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		closein = closeout = 1;
916f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
917f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
918f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (closeout && (fd == channel->readfd)) {
919f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		channel->readfd = FD_CLOSED;
920f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
921f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (closeout && ERRFD_IS_READ(channel) && (fd == channel->errfd)) {
922f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		channel->errfd = FD_CLOSED;
923f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
924f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
925f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (closein && fd == channel->writefd) {
926f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		channel->writefd = FD_CLOSED;
927f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
928f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (closein && ERRFD_IS_WRITE(channel) && (fd == channel->errfd)) {
929f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		channel->errfd = FD_CLOSED;
930f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
931f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
932f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* if we called shutdown on it and all references are gone, then we
933f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	 * need to close() it to stop it lingering */
934f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (channel->type->sepfds && channel->readfd == FD_CLOSED
935f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		&& channel->writefd == FD_CLOSED && channel->errfd == FD_CLOSED) {
936f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("CLOSE (finally) of %d", fd))
937f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		close(fd);
938f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
939f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
940f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
941f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
942f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#if defined(USING_LISTENERS) || defined(DROPBEAR_CLIENT)
943f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Create a new channel, and start the open request. This is intended
944f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * for X11, agent, tcp forwarding, and should be filled with channel-specific
945f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * options, with the calling function calling encrypt_packet() after
946f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * completion. It is mandatory for the caller to encrypt_packet() if
947f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * DROPBEAR_SUCCESS is returned */
948f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint send_msg_channel_open_init(int fd, const struct ChanType *type) {
949f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
950f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	struct Channel* chan;
951f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
952f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("enter send_msg_channel_open_init()"))
953f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	chan = newchannel(0, type, 0, 0);
954f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (!chan) {
955f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		TRACE(("leave send_msg_channel_open_init() - FAILED in newchannel()"))
956f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		return DROPBEAR_FAILURE;
957f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
958f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
959f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* set fd non-blocking */
960f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	setnonblocking(fd);
961f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
962f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	chan->writefd = chan->readfd = fd;
963f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	ses.maxfd = MAX(ses.maxfd, fd);
964f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
965f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	chan->await_open = 1;
966f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
967f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* now open the channel connection */
968f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	CHECKCLEARTOWRITE();
969f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
970f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN);
971f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putstring(ses.writepayload, type->name, strlen(type->name));
972f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putint(ses.writepayload, chan->index);
973f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putint(ses.writepayload, RECV_MAXWINDOW);
974f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	buf_putint(ses.writepayload, RECV_MAXPACKET);
975f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
976f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("leave send_msg_channel_open_init()"))
977f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	return DROPBEAR_SUCCESS;
978f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
979f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
980f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Confirmation that our channel open request (for forwardings) was
981f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * successful*/
982f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid recv_msg_channel_open_confirmation() {
983f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
984f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	struct Channel * channel;
985f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	int ret;
986f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
987f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("enter recv_msg_channel_open_confirmation"))
988f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
989f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	channel = getchannel();
990f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
991f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (!channel->await_open) {
992f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		dropbear_exit("unexpected channel reply");
993f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
994f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	channel->await_open = 0;
995f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
996f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	channel->remotechan =  buf_getint(ses.payload);
997f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	channel->transwindow = buf_getint(ses.payload);
998f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	channel->transmaxpacket = buf_getint(ses.payload);
999f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
1000f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("new chan remote %d local %d",
1001f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project				channel->remotechan, channel->index))
1002f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
1003f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	/* Run the inithandler callback */
1004f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (channel->type->inithandler) {
1005f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		ret = channel->type->inithandler(channel);
1006f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		if (ret > 0) {
1007f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			remove_channel(channel);
1008f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project			TRACE(("inithandler returned failure %d", ret))
1009f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		}
1010f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
1011f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
1012f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
1013f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	TRACE(("leave recv_msg_channel_open_confirmation"))
1014f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
1015f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
1016f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Notification that our channel open request failed */
1017f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid recv_msg_channel_open_failure() {
1018f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
1019f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	struct Channel * channel;
1020f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
1021f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	channel = getchannel();
1022f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
1023f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	if (!channel->await_open) {
1024f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project		dropbear_exit("unexpected channel reply");
1025f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	}
1026f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	channel->await_open = 0;
1027f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
1028f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project	remove_channel(channel);
1029f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
1030f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif /* USING_LISTENERS */
1031