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