Changes to update Tomato RAF.
[tomato.git] / release / src / router / dropbear / common-channel.c
blob9eaba5090779cd63c40e80bf5f69f67e55b525b9
1 /*
2 * Dropbear SSH
3 *
4 * Copyright (c) 2002-2004 Matt Johnston
5 * All rights reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE. */
25 /* Handle the multiplexed channels, such as sessions, x11, agent connections */
27 #include "includes.h"
28 #include "session.h"
29 #include "packet.h"
30 #include "ssh.h"
31 #include "buffer.h"
32 #include "circbuffer.h"
33 #include "dbutil.h"
34 #include "channel.h"
35 #include "ssh.h"
36 #include "listener.h"
37 #include "runopts.h"
39 static void send_msg_channel_open_failure(unsigned int remotechan, int reason,
40 const unsigned char *text, const unsigned char *lang);
41 static void send_msg_channel_open_confirmation(struct Channel* channel,
42 unsigned int recvwindow,
43 unsigned int recvmaxpacket);
44 static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf);
45 static void send_msg_channel_window_adjust(struct Channel *channel,
46 unsigned int incr);
47 static void send_msg_channel_data(struct Channel *channel, int isextended);
48 static void send_msg_channel_eof(struct Channel *channel);
49 static void send_msg_channel_close(struct Channel *channel);
50 static void remove_channel(struct Channel *channel);
51 static void delete_channel(struct Channel *channel);
52 static void check_in_progress(struct Channel *channel);
53 static unsigned int write_pending(struct Channel * channel);
54 static void check_close(struct Channel *channel);
55 static void close_chan_fd(struct Channel *channel, int fd, int how);
57 #define FD_UNINIT (-2)
58 #define FD_CLOSED (-1)
60 #define ERRFD_IS_READ(channel) ((channel)->extrabuf == NULL)
61 #define ERRFD_IS_WRITE(channel) (!ERRFD_IS_READ(channel))
63 /* Initialise all the channels */
64 void chaninitialise(const struct ChanType *chantypes[]) {
66 /* may as well create space for a single channel */
67 ses.channels = (struct Channel**)m_malloc(sizeof(struct Channel*));
68 ses.chansize = 1;
69 ses.channels[0] = NULL;
70 ses.chancount = 0;
72 ses.chantypes = chantypes;
74 #ifdef USING_LISTENERS
75 listeners_initialise();
76 #endif
80 /* Clean up channels, freeing allocated memory */
81 void chancleanup() {
83 unsigned int i;
85 TRACE(("enter chancleanup"))
86 for (i = 0; i < ses.chansize; i++) {
87 if (ses.channels[i] != NULL) {
88 TRACE(("channel %d closing", i))
89 remove_channel(ses.channels[i]);
92 m_free(ses.channels);
93 TRACE(("leave chancleanup"))
96 /* Create a new channel entry, send a reply confirm or failure */
97 /* If remotechan, transwindow and transmaxpacket are not know (for a new
98 * outgoing connection, with them to be filled on confirmation), they should
99 * all be set to 0 */
100 struct Channel* newchannel(unsigned int remotechan,
101 const struct ChanType *type,
102 unsigned int transwindow, unsigned int transmaxpacket) {
104 struct Channel * newchan;
105 unsigned int i, j;
107 TRACE(("enter newchannel"))
109 /* first see if we can use existing channels */
110 for (i = 0; i < ses.chansize; i++) {
111 if (ses.channels[i] == NULL) {
112 break;
116 /* otherwise extend the list */
117 if (i == ses.chansize) {
118 if (ses.chansize >= MAX_CHANNELS) {
119 TRACE(("leave newchannel: max chans reached"))
120 return NULL;
123 /* extend the channels */
124 ses.channels = (struct Channel**)m_realloc(ses.channels,
125 (ses.chansize+CHAN_EXTEND_SIZE)*sizeof(struct Channel*));
127 ses.chansize += CHAN_EXTEND_SIZE;
129 /* set the new channels to null */
130 for (j = i; j < ses.chansize; j++) {
131 ses.channels[j] = NULL;
136 newchan = (struct Channel*)m_malloc(sizeof(struct Channel));
137 newchan->type = type;
138 newchan->index = i;
139 newchan->sent_close = newchan->recv_close = 0;
140 newchan->sent_eof = newchan->recv_eof = 0;
141 newchan->close_handler_done = 0;
143 newchan->remotechan = remotechan;
144 newchan->transwindow = transwindow;
145 newchan->transmaxpacket = transmaxpacket;
147 newchan->typedata = NULL;
148 newchan->writefd = FD_UNINIT;
149 newchan->readfd = FD_UNINIT;
150 newchan->errfd = FD_CLOSED; /* this isn't always set to start with */
151 newchan->initconn = 0;
152 newchan->await_open = 0;
153 newchan->flushing = 0;
155 newchan->writebuf = cbuf_new(opts.recv_window);
156 newchan->extrabuf = NULL; /* The user code can set it up */
157 newchan->recvwindow = opts.recv_window;
158 newchan->recvdonelen = 0;
159 newchan->recvmaxpacket = RECV_MAX_PAYLOAD_LEN;
161 ses.channels[i] = newchan;
162 ses.chancount++;
164 TRACE(("leave newchannel"))
166 return newchan;
169 /* Returns the channel structure corresponding to the channel in the current
170 * data packet (ses.payload must be positioned appropriately).
171 * A valid channel is always returns, it will fail fatally with an unknown
172 * channel */
173 static struct Channel* getchannel_msg(const char* kind) {
175 unsigned int chan;
177 chan = buf_getint(ses.payload);
178 if (chan >= ses.chansize || ses.channels[chan] == NULL) {
179 if (kind) {
180 dropbear_exit("%s for unknown channel %d", kind, chan);
181 } else {
182 dropbear_exit("Unknown channel %d", chan);
185 return ses.channels[chan];
188 struct Channel* getchannel() {
189 return getchannel_msg(NULL);
192 /* Iterate through the channels, performing IO if available */
193 void channelio(fd_set *readfds, fd_set *writefds) {
195 struct Channel *channel;
196 unsigned int i;
198 /* foreach channel */
199 for (i = 0; i < ses.chansize; i++) {
201 channel = ses.channels[i];
202 if (channel == NULL) {
203 /* only process in-use channels */
204 continue;
207 /* read data and send it over the wire */
208 if (channel->readfd >= 0 && FD_ISSET(channel->readfd, readfds)) {
209 TRACE(("send normal readfd"))
210 send_msg_channel_data(channel, 0);
213 /* read stderr data and send it over the wire */
214 if (ERRFD_IS_READ(channel) && channel->errfd >= 0
215 && FD_ISSET(channel->errfd, readfds)) {
216 TRACE(("send normal errfd"))
217 send_msg_channel_data(channel, 1);
220 /* write to program/pipe stdin */
221 if (channel->writefd >= 0 && FD_ISSET(channel->writefd, writefds)) {
222 if (channel->initconn) {
223 /* XXX should this go somewhere cleaner? */
224 check_in_progress(channel);
225 continue; /* Important not to use the channel after
226 check_in_progress(), as it may be NULL */
228 writechannel(channel, channel->writefd, channel->writebuf);
231 /* stderr for client mode */
232 if (ERRFD_IS_WRITE(channel)
233 && channel->errfd >= 0 && FD_ISSET(channel->errfd, writefds)) {
234 writechannel(channel, channel->errfd, channel->extrabuf);
237 /* handle any channel closing etc */
238 check_close(channel);
242 /* Listeners such as TCP, X11, agent-auth */
243 #ifdef USING_LISTENERS
244 handle_listeners(readfds);
245 #endif
249 /* Returns true if there is data remaining to be written to stdin or
250 * stderr of a channel's endpoint. */
251 static unsigned int write_pending(struct Channel * channel) {
253 if (channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0) {
254 return 1;
255 } else if (channel->errfd >= 0 && channel->extrabuf &&
256 cbuf_getused(channel->extrabuf) > 0) {
257 return 1;
259 return 0;
263 /* EOF/close handling */
264 static void check_close(struct Channel *channel) {
265 int close_allowed = 0;
267 TRACE(("check_close: writefd %d, readfd %d, errfd %d, sent_close %d, recv_close %d",
268 channel->writefd, channel->readfd,
269 channel->errfd, channel->sent_close, channel->recv_close))
270 TRACE(("writebuf size %d extrabuf size %d",
271 cbuf_getused(channel->writebuf),
272 channel->extrabuf ? cbuf_getused(channel->extrabuf) : 0))
274 if (!channel->flushing
275 && !channel->close_handler_done
276 && channel->type->check_close
277 && channel->type->check_close(channel))
279 channel->flushing = 1;
282 /* if a type-specific check_close is defined we will only exit
283 once that has been triggered. this is only used for a server "session"
284 channel, to ensure that the shell has exited (and the exit status
285 retrieved) before we close things up. */
286 if (!channel->type->check_close
287 || channel->close_handler_done
288 || channel->type->check_close(channel)) {
289 close_allowed = 1;
292 if (channel->recv_close && !write_pending(channel) && close_allowed) {
293 if (!channel->sent_close) {
294 TRACE(("Sending MSG_CHANNEL_CLOSE in response to same."))
295 send_msg_channel_close(channel);
297 remove_channel(channel);
298 return;
301 if (channel->recv_eof && !write_pending(channel)) {
302 close_chan_fd(channel, channel->writefd, SHUT_WR);
305 /* Special handling for flushing read data after an exit. We
306 read regardless of whether the select FD was set,
307 and if there isn't data available, the channel will get closed. */
308 if (channel->flushing) {
309 TRACE(("might send data, flushing"))
310 if (channel->readfd >= 0 && channel->transwindow > 0) {
311 TRACE(("send data readfd"))
312 send_msg_channel_data(channel, 0);
314 if (ERRFD_IS_READ(channel) && channel->errfd >= 0
315 && channel->transwindow > 0) {
316 TRACE(("send data errfd"))
317 send_msg_channel_data(channel, 1);
321 /* If we're not going to send any more data, send EOF */
322 if (!channel->sent_eof
323 && channel->readfd == FD_CLOSED
324 && (ERRFD_IS_WRITE(channel) || channel->errfd == FD_CLOSED)) {
325 send_msg_channel_eof(channel);
328 /* And if we can't receive any more data from them either, close up */
329 if (channel->readfd == FD_CLOSED
330 && (ERRFD_IS_WRITE(channel) || channel->errfd == FD_CLOSED)
331 && !channel->sent_close
332 && close_allowed
333 && !write_pending(channel)) {
334 TRACE(("sending close, readfd is closed"))
335 send_msg_channel_close(channel);
339 /* Check whether a deferred (EINPROGRESS) connect() was successful, and
340 * if so, set up the channel properly. Otherwise, the channel is cleaned up, so
341 * it is important that the channel reference isn't used after a call to this
342 * function */
343 static void check_in_progress(struct Channel *channel) {
345 int val;
346 socklen_t vallen = sizeof(val);
348 TRACE(("enter check_in_progress"))
350 if (getsockopt(channel->writefd, SOL_SOCKET, SO_ERROR, &val, &vallen)
351 || val != 0) {
352 send_msg_channel_open_failure(channel->remotechan,
353 SSH_OPEN_CONNECT_FAILED, "", "");
354 close(channel->writefd);
355 delete_channel(channel);
356 TRACE(("leave check_in_progress: fail"))
357 } else {
358 send_msg_channel_open_confirmation(channel, channel->recvwindow,
359 channel->recvmaxpacket);
360 channel->readfd = channel->writefd;
361 channel->initconn = 0;
362 TRACE(("leave check_in_progress: success"))
367 /* Send the close message and set the channel as closed */
368 static void send_msg_channel_close(struct Channel *channel) {
370 TRACE(("enter send_msg_channel_close %p", channel))
371 if (channel->type->closehandler
372 && !channel->close_handler_done) {
373 channel->type->closehandler(channel);
374 channel->close_handler_done = 1;
377 CHECKCLEARTOWRITE();
379 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_CLOSE);
380 buf_putint(ses.writepayload, channel->remotechan);
382 encrypt_packet();
384 channel->sent_eof = 1;
385 channel->sent_close = 1;
386 close_chan_fd(channel, channel->readfd, SHUT_RD);
387 close_chan_fd(channel, channel->errfd, SHUT_RDWR);
388 close_chan_fd(channel, channel->writefd, SHUT_WR);
389 TRACE(("leave send_msg_channel_close"))
392 /* call this when trans/eof channels are closed */
393 static void send_msg_channel_eof(struct Channel *channel) {
395 TRACE(("enter send_msg_channel_eof"))
396 CHECKCLEARTOWRITE();
398 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_EOF);
399 buf_putint(ses.writepayload, channel->remotechan);
401 encrypt_packet();
403 channel->sent_eof = 1;
405 TRACE(("leave send_msg_channel_eof"))
408 /* Called to write data out to the local side of the channel.
409 * Only called when we know we can write to a channel, writes as much as
410 * possible */
411 static void writechannel(struct Channel* channel, int fd, circbuffer *cbuf) {
413 int len, maxlen;
415 TRACE(("enter writechannel fd %d", fd))
417 maxlen = cbuf_readlen(cbuf);
419 /* Write the data out */
420 len = write(fd, cbuf_readptr(cbuf, maxlen), maxlen);
421 if (len <= 0) {
422 TRACE(("errno %d len %d", errno, len))
423 if (len < 0 && errno != EINTR) {
424 close_chan_fd(channel, fd, SHUT_WR);
426 TRACE(("leave writechannel: len <= 0"))
427 return;
429 TRACE(("writechannel wrote %d", len))
431 cbuf_incrread(cbuf, len);
432 channel->recvdonelen += len;
434 /* Window adjust handling */
435 if (channel->recvdonelen >= RECV_WINDOWEXTEND) {
436 /* Set it back to max window */
437 send_msg_channel_window_adjust(channel, channel->recvdonelen);
438 channel->recvwindow += channel->recvdonelen;
439 channel->recvdonelen = 0;
442 dropbear_assert(channel->recvwindow <= opts.recv_window);
443 dropbear_assert(channel->recvwindow <= cbuf_getavail(channel->writebuf));
444 dropbear_assert(channel->extrabuf == NULL ||
445 channel->recvwindow <= cbuf_getavail(channel->extrabuf));
447 TRACE(("leave writechannel"))
450 /* Set the file descriptors for the main select in session.c
451 * This avoid channels which don't have any window available, are closed, etc*/
452 void setchannelfds(fd_set *readfds, fd_set *writefds) {
454 unsigned int i;
455 struct Channel * channel;
457 for (i = 0; i < ses.chansize; i++) {
459 channel = ses.channels[i];
460 if (channel == NULL) {
461 continue;
464 /* Stuff to put over the wire */
465 if (channel->transwindow > 0) {
467 if (channel->readfd >= 0) {
468 FD_SET(channel->readfd, readfds);
471 if (ERRFD_IS_READ(channel) && channel->errfd >= 0) {
472 FD_SET(channel->errfd, readfds);
476 /* Stuff from the wire */
477 if ((channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0 )
478 || channel->initconn) {
479 FD_SET(channel->writefd, writefds);
482 if (ERRFD_IS_WRITE(channel) && channel->errfd >= 0
483 && cbuf_getused(channel->extrabuf) > 0 ) {
484 FD_SET(channel->errfd, writefds);
487 } /* foreach channel */
489 #ifdef USING_LISTENERS
490 set_listener_fds(readfds);
491 #endif
495 /* handle the channel EOF event, by closing the channel filedescriptor. The
496 * channel isn't closed yet, it is left until the incoming (from the program
497 * etc) FD is also EOF */
498 void recv_msg_channel_eof() {
500 struct Channel * channel;
502 TRACE(("enter recv_msg_channel_eof"))
504 channel = getchannel_msg("EOF");
506 channel->recv_eof = 1;
508 check_close(channel);
509 TRACE(("leave recv_msg_channel_eof"))
513 /* Handle channel closure(), respond in kind and close the channels */
514 void recv_msg_channel_close() {
516 struct Channel * channel;
518 TRACE(("enter recv_msg_channel_close"))
520 channel = getchannel_msg("Close");
522 channel->recv_eof = 1;
523 channel->recv_close = 1;
525 check_close(channel);
526 TRACE(("leave recv_msg_channel_close"))
529 /* Remove a channel entry, this is only executed after both sides have sent
530 * channel close */
531 static void remove_channel(struct Channel * channel) {
533 TRACE(("enter remove_channel"))
534 TRACE(("channel index is %d", channel->index))
536 cbuf_free(channel->writebuf);
537 channel->writebuf = NULL;
539 if (channel->extrabuf) {
540 cbuf_free(channel->extrabuf);
541 channel->extrabuf = NULL;
545 /* close the FDs in case they haven't been done
546 * yet (they might have been shutdown etc) */
547 TRACE(("CLOSE writefd %d", channel->writefd))
548 close(channel->writefd);
549 TRACE(("CLOSE readfd %d", channel->readfd))
550 close(channel->readfd);
551 TRACE(("CLOSE errfd %d", channel->errfd))
552 close(channel->errfd);
554 channel->typedata = NULL;
556 delete_channel(channel);
558 TRACE(("leave remove_channel"))
561 /* Remove a channel entry */
562 static void delete_channel(struct Channel *channel) {
564 ses.channels[channel->index] = NULL;
565 m_free(channel);
566 ses.chancount--;
571 /* Handle channel specific requests, passing off to corresponding handlers
572 * such as chansession or x11fwd */
573 void recv_msg_channel_request() {
575 struct Channel *channel;
577 channel = getchannel();
579 TRACE(("enter recv_msg_channel_request %p", channel))
581 if (channel->sent_close) {
582 TRACE(("leave recv_msg_channel_request: already closed channel"))
583 return;
586 if (channel->type->reqhandler
587 && !channel->close_handler_done) {
588 channel->type->reqhandler(channel);
589 } else {
590 send_msg_channel_failure(channel);
593 TRACE(("leave recv_msg_channel_request"))
597 /* Reads data from the server's program/shell/etc, and puts it in a
598 * channel_data packet to send.
599 * chan is the remote channel, isextended is 0 if it is normal data, 1
600 * if it is extended data. if it is extended, then the type is in
601 * exttype */
602 static void send_msg_channel_data(struct Channel *channel, int isextended) {
604 int len;
605 size_t maxlen, size_pos;
606 int fd;
608 CHECKCLEARTOWRITE();
610 TRACE(("enter send_msg_channel_data"))
611 dropbear_assert(!channel->sent_close);
613 if (isextended) {
614 fd = channel->errfd;
615 } else {
616 fd = channel->readfd;
618 TRACE(("enter send_msg_channel_data isextended %d fd %d", isextended, fd))
619 dropbear_assert(fd >= 0);
621 maxlen = MIN(channel->transwindow, channel->transmaxpacket);
622 /* -(1+4+4) is SSH_MSG_CHANNEL_DATA, channel number, string length, and
623 * exttype if is extended */
624 maxlen = MIN(maxlen,
625 ses.writepayload->size - 1 - 4 - 4 - (isextended ? 4 : 0));
626 TRACE(("maxlen %d", maxlen))
627 if (maxlen == 0) {
628 TRACE(("leave send_msg_channel_data: no window"))
629 return;
632 buf_putbyte(ses.writepayload,
633 isextended ? SSH_MSG_CHANNEL_EXTENDED_DATA : SSH_MSG_CHANNEL_DATA);
634 buf_putint(ses.writepayload, channel->remotechan);
635 if (isextended) {
636 buf_putint(ses.writepayload, SSH_EXTENDED_DATA_STDERR);
638 /* a dummy size first ...*/
639 size_pos = ses.writepayload->pos;
640 buf_putint(ses.writepayload, 0);
642 /* read the data */
643 len = read(fd, buf_getwriteptr(ses.writepayload, maxlen), maxlen);
644 if (len <= 0) {
645 if (len == 0 || errno != EINTR) {
646 /* This will also get hit in the case of EAGAIN. The only
647 time we expect to receive EAGAIN is when we're flushing a FD,
648 in which case it can be treated the same as EOF */
649 close_chan_fd(channel, fd, SHUT_RD);
651 ses.writepayload->len = ses.writepayload->pos = 0;
652 TRACE(("leave send_msg_channel_data: len %d read err %d or EOF for fd %d",
653 len, errno, fd))
654 return;
656 buf_incrwritepos(ses.writepayload, len);
657 /* ... real size here */
658 buf_setpos(ses.writepayload, size_pos);
659 buf_putint(ses.writepayload, len);
661 channel->transwindow -= len;
663 encrypt_packet();
665 /* If we receive less data than we requested when flushing, we've
666 reached the equivalent of EOF */
667 if (channel->flushing && len < (ssize_t)maxlen)
669 TRACE(("closing from channel, flushing out."))
670 close_chan_fd(channel, fd, SHUT_RD);
672 TRACE(("leave send_msg_channel_data"))
675 /* We receive channel data */
676 void recv_msg_channel_data() {
678 struct Channel *channel;
680 channel = getchannel();
682 common_recv_msg_channel_data(channel, channel->writefd, channel->writebuf);
685 /* Shared for data and stderr data - when we receive data, put it in a buffer
686 * for writing to the local file descriptor */
687 void common_recv_msg_channel_data(struct Channel *channel, int fd,
688 circbuffer * cbuf) {
690 unsigned int datalen;
691 unsigned int maxdata;
692 unsigned int buflen;
693 unsigned int len;
695 TRACE(("enter recv_msg_channel_data"))
697 if (channel->recv_eof) {
698 dropbear_exit("Received data after eof");
701 if (fd < 0) {
702 /* If we have encountered failed write, the far side might still
703 * be sending data without having yet received our close notification.
704 * We just drop the data. */
705 return;
708 datalen = buf_getint(ses.payload);
709 TRACE(("length %d", datalen))
711 maxdata = cbuf_getavail(cbuf);
713 /* Whilst the spec says we "MAY ignore data past the end" this could
714 * lead to corrupted file transfers etc (chunks missed etc). It's better to
715 * just die horribly */
716 if (datalen > maxdata) {
717 dropbear_exit("Oversized packet");
720 /* We may have to run throught twice, if the buffer wraps around. Can't
721 * just "leave it for next time" like with writechannel, since this
722 * is payload data */
723 len = datalen;
724 while (len > 0) {
725 buflen = cbuf_writelen(cbuf);
726 buflen = MIN(buflen, len);
728 memcpy(cbuf_writeptr(cbuf, buflen),
729 buf_getptr(ses.payload, buflen), buflen);
730 cbuf_incrwrite(cbuf, buflen);
731 buf_incrpos(ses.payload, buflen);
732 len -= buflen;
735 dropbear_assert(channel->recvwindow >= datalen);
736 channel->recvwindow -= datalen;
737 dropbear_assert(channel->recvwindow <= opts.recv_window);
739 TRACE(("leave recv_msg_channel_data"))
742 /* Increment the outgoing data window for a channel - the remote end limits
743 * the amount of data which may be transmitted, this window is decremented
744 * as data is sent, and incremented upon receiving window-adjust messages */
745 void recv_msg_channel_window_adjust() {
747 struct Channel * channel;
748 unsigned int incr;
750 channel = getchannel();
752 incr = buf_getint(ses.payload);
753 TRACE(("received window increment %d", incr))
754 incr = MIN(incr, TRANS_MAX_WIN_INCR);
756 channel->transwindow += incr;
757 channel->transwindow = MIN(channel->transwindow, TRANS_MAX_WINDOW);
761 /* Increment the incoming data window for a channel, and let the remote
762 * end know */
763 static void send_msg_channel_window_adjust(struct Channel* channel,
764 unsigned int incr) {
766 TRACE(("sending window adjust %d", incr))
767 CHECKCLEARTOWRITE();
769 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_WINDOW_ADJUST);
770 buf_putint(ses.writepayload, channel->remotechan);
771 buf_putint(ses.writepayload, incr);
773 encrypt_packet();
776 /* Handle a new channel request, performing any channel-type-specific setup */
777 void recv_msg_channel_open() {
779 unsigned char *type;
780 unsigned int typelen;
781 unsigned int remotechan, transwindow, transmaxpacket;
782 struct Channel *channel;
783 const struct ChanType **cp;
784 const struct ChanType *chantype;
785 unsigned int errtype = SSH_OPEN_UNKNOWN_CHANNEL_TYPE;
786 int ret;
789 TRACE(("enter recv_msg_channel_open"))
791 /* get the packet contents */
792 type = buf_getstring(ses.payload, &typelen);
794 remotechan = buf_getint(ses.payload);
795 transwindow = buf_getint(ses.payload);
796 transwindow = MIN(transwindow, TRANS_MAX_WINDOW);
797 transmaxpacket = buf_getint(ses.payload);
798 transmaxpacket = MIN(transmaxpacket, TRANS_MAX_PAYLOAD_LEN);
800 /* figure what type of packet it is */
801 if (typelen > MAX_NAME_LEN) {
802 goto failure;
805 /* Get the channel type. Client and server style invokation will set up a
806 * different list for ses.chantypes at startup. We just iterate through
807 * this list and find the matching name */
808 for (cp = &ses.chantypes[0], chantype = (*cp);
809 chantype != NULL;
810 cp++, chantype = (*cp)) {
811 if (strcmp(type, chantype->name) == 0) {
812 break;
816 if (chantype == NULL) {
817 TRACE(("No matching type for '%s'", type))
818 goto failure;
821 TRACE(("matched type '%s'", type))
823 /* create the channel */
824 channel = newchannel(remotechan, chantype, transwindow, transmaxpacket);
826 if (channel == NULL) {
827 TRACE(("newchannel returned NULL"))
828 goto failure;
831 if (channel->type->inithandler) {
832 ret = channel->type->inithandler(channel);
833 if (ret == SSH_OPEN_IN_PROGRESS) {
834 /* We'll send the confirmation later */
835 goto cleanup;
837 if (ret > 0) {
838 errtype = ret;
839 delete_channel(channel);
840 TRACE(("inithandler returned failure %d", ret))
841 goto failure;
845 /* success */
846 send_msg_channel_open_confirmation(channel, channel->recvwindow,
847 channel->recvmaxpacket);
848 goto cleanup;
850 failure:
851 TRACE(("recv_msg_channel_open failure"))
852 send_msg_channel_open_failure(remotechan, errtype, "", "");
854 cleanup:
855 m_free(type);
857 TRACE(("leave recv_msg_channel_open"))
860 /* Send a failure message */
861 void send_msg_channel_failure(struct Channel *channel) {
863 TRACE(("enter send_msg_channel_failure"))
864 CHECKCLEARTOWRITE();
866 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_FAILURE);
867 buf_putint(ses.writepayload, channel->remotechan);
869 encrypt_packet();
870 TRACE(("leave send_msg_channel_failure"))
873 /* Send a success message */
874 void send_msg_channel_success(struct Channel *channel) {
876 TRACE(("enter send_msg_channel_success"))
877 CHECKCLEARTOWRITE();
879 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_SUCCESS);
880 buf_putint(ses.writepayload, channel->remotechan);
882 encrypt_packet();
883 TRACE(("leave send_msg_channel_success"))
886 /* Send a channel open failure message, with a corresponding reason
887 * code (usually resource shortage or unknown chan type) */
888 static void send_msg_channel_open_failure(unsigned int remotechan,
889 int reason, const unsigned char *text, const unsigned char *lang) {
891 TRACE(("enter send_msg_channel_open_failure"))
892 CHECKCLEARTOWRITE();
894 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN_FAILURE);
895 buf_putint(ses.writepayload, remotechan);
896 buf_putint(ses.writepayload, reason);
897 buf_putstring(ses.writepayload, text, strlen((char*)text));
898 buf_putstring(ses.writepayload, lang, strlen((char*)lang));
900 encrypt_packet();
901 TRACE(("leave send_msg_channel_open_failure"))
904 /* Confirm a channel open, and let the remote end know what number we've
905 * allocated and the receive parameters */
906 static void send_msg_channel_open_confirmation(struct Channel* channel,
907 unsigned int recvwindow,
908 unsigned int recvmaxpacket) {
910 TRACE(("enter send_msg_channel_open_confirmation"))
911 CHECKCLEARTOWRITE();
913 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
914 buf_putint(ses.writepayload, channel->remotechan);
915 buf_putint(ses.writepayload, channel->index);
916 buf_putint(ses.writepayload, recvwindow);
917 buf_putint(ses.writepayload, recvmaxpacket);
919 encrypt_packet();
920 TRACE(("leave send_msg_channel_open_confirmation"))
923 /* close a fd, how is SHUT_RD or SHUT_WR */
924 static void close_chan_fd(struct Channel *channel, int fd, int how) {
926 int closein = 0, closeout = 0;
928 if (channel->type->sepfds) {
929 TRACE(("SHUTDOWN(%d, %d)", fd, how))
930 shutdown(fd, how);
931 if (how == 0) {
932 closeout = 1;
933 } else {
934 closein = 1;
936 } else {
937 TRACE(("CLOSE some fd %d", fd))
938 close(fd);
939 closein = closeout = 1;
942 if (closeout && (fd == channel->readfd)) {
943 channel->readfd = FD_CLOSED;
945 if (closeout && ERRFD_IS_READ(channel) && (fd == channel->errfd)) {
946 channel->errfd = FD_CLOSED;
949 if (closein && fd == channel->writefd) {
950 channel->writefd = FD_CLOSED;
952 if (closein && ERRFD_IS_WRITE(channel) && (fd == channel->errfd)) {
953 channel->errfd = FD_CLOSED;
956 /* if we called shutdown on it and all references are gone, then we
957 * need to close() it to stop it lingering */
958 if (channel->type->sepfds && channel->readfd == FD_CLOSED
959 && channel->writefd == FD_CLOSED && channel->errfd == FD_CLOSED) {
960 TRACE(("CLOSE (finally) of %d", fd))
961 close(fd);
966 #if defined(USING_LISTENERS) || defined(DROPBEAR_CLIENT)
967 /* Create a new channel, and start the open request. This is intended
968 * for X11, agent, tcp forwarding, and should be filled with channel-specific
969 * options, with the calling function calling encrypt_packet() after
970 * completion. It is mandatory for the caller to encrypt_packet() if
971 * DROPBEAR_SUCCESS is returned */
972 int send_msg_channel_open_init(int fd, const struct ChanType *type) {
974 struct Channel* chan;
976 TRACE(("enter send_msg_channel_open_init()"))
977 chan = newchannel(0, type, 0, 0);
978 if (!chan) {
979 TRACE(("leave send_msg_channel_open_init() - FAILED in newchannel()"))
980 return DROPBEAR_FAILURE;
983 /* set fd non-blocking */
984 setnonblocking(fd);
986 chan->writefd = chan->readfd = fd;
987 ses.maxfd = MAX(ses.maxfd, fd);
989 chan->await_open = 1;
991 /* now open the channel connection */
992 CHECKCLEARTOWRITE();
994 buf_putbyte(ses.writepayload, SSH_MSG_CHANNEL_OPEN);
995 buf_putstring(ses.writepayload, type->name, strlen(type->name));
996 buf_putint(ses.writepayload, chan->index);
997 buf_putint(ses.writepayload, opts.recv_window);
998 buf_putint(ses.writepayload, RECV_MAX_PAYLOAD_LEN);
1000 TRACE(("leave send_msg_channel_open_init()"))
1001 return DROPBEAR_SUCCESS;
1004 /* Confirmation that our channel open request (for forwardings) was
1005 * successful*/
1006 void recv_msg_channel_open_confirmation() {
1008 struct Channel * channel;
1009 int ret;
1011 TRACE(("enter recv_msg_channel_open_confirmation"))
1013 channel = getchannel();
1015 if (!channel->await_open) {
1016 dropbear_exit("Unexpected channel reply");
1018 channel->await_open = 0;
1020 channel->remotechan = buf_getint(ses.payload);
1021 channel->transwindow = buf_getint(ses.payload);
1022 channel->transmaxpacket = buf_getint(ses.payload);
1024 TRACE(("new chan remote %d local %d",
1025 channel->remotechan, channel->index))
1027 /* Run the inithandler callback */
1028 if (channel->type->inithandler) {
1029 ret = channel->type->inithandler(channel);
1030 if (ret > 0) {
1031 remove_channel(channel);
1032 TRACE(("inithandler returned failure %d", ret))
1037 TRACE(("leave recv_msg_channel_open_confirmation"))
1040 /* Notification that our channel open request failed */
1041 void recv_msg_channel_open_failure() {
1043 struct Channel * channel;
1045 channel = getchannel();
1047 if (!channel->await_open) {
1048 dropbear_exit("Unexpected channel reply");
1050 channel->await_open = 0;
1052 remove_channel(channel);
1054 #endif /* USING_LISTENERS */