summaryrefslogtreecommitdiff
path: root/channels.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2008-05-19 15:05:07 +1000
committerDamien Miller <djm@mindrot.org>2008-05-19 15:05:07 +1000
commitb84886ba3e362f54b70aefcbe1aa10606309b7d7 (patch)
tree9346734369c4e527eca83c87a89c05df0ffe4a18 /channels.c
parentdb255cad0531047a3e35a95af74ad2e03b054412 (diff)
- djm@cvs.openbsd.org 2008/05/08 12:02:23
[auth-options.c auth1.c channels.c channels.h clientloop.c gss-serv.c] [monitor.c monitor_wrap.c nchan.c servconf.c serverloop.c session.c] [ssh.c sshd.c] Implement a channel success/failure status confirmation callback mechanism. Each channel maintains a queue of callbacks, which will be drained in order (RFC4253 guarantees confirm messages are not reordered within an channel). Also includes a abandonment callback to clean up if a channel is closed without sending confirmation messages. This probably shouldn't happen in compliant implementations, but it could be abused to leak memory. ok markus@ (as part of a larger diff)
Diffstat (limited to 'channels.c')
-rw-r--r--channels.c73
1 files changed, 64 insertions, 9 deletions
diff --git a/channels.c b/channels.c
index 05c23e59c..b5e28dabf 100644
--- a/channels.c
+++ b/channels.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: channels.c,v 1.274 2008/05/08 06:59:01 markus Exp $ */ 1/* $OpenBSD: channels.c,v 1.275 2008/05/08 12:02:23 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -61,6 +61,7 @@
61#include <unistd.h> 61#include <unistd.h>
62#include <stdarg.h> 62#include <stdarg.h>
63 63
64#include "openbsd-compat/sys-queue.h"
64#include "xmalloc.h" 65#include "xmalloc.h"
65#include "ssh.h" 66#include "ssh.h"
66#include "ssh1.h" 67#include "ssh1.h"
@@ -319,10 +320,11 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd,
319 c->single_connection = 0; 320 c->single_connection = 0;
320 c->detach_user = NULL; 321 c->detach_user = NULL;
321 c->detach_close = 0; 322 c->detach_close = 0;
322 c->confirm = NULL; 323 c->open_confirm = NULL;
323 c->confirm_ctx = NULL; 324 c->open_confirm_ctx = NULL;
324 c->input_filter = NULL; 325 c->input_filter = NULL;
325 c->output_filter = NULL; 326 c->output_filter = NULL;
327 TAILQ_INIT(&c->status_confirms);
326 debug("channel %d: new [%s]", found, remote_name); 328 debug("channel %d: new [%s]", found, remote_name);
327 return c; 329 return c;
328} 330}
@@ -379,6 +381,7 @@ channel_free(Channel *c)
379{ 381{
380 char *s; 382 char *s;
381 u_int i, n; 383 u_int i, n;
384 struct channel_confirm *cc;
382 385
383 for (n = 0, i = 0; i < channels_alloc; i++) 386 for (n = 0, i = 0; i < channels_alloc; i++)
384 if (channels[i]) 387 if (channels[i])
@@ -402,6 +405,13 @@ channel_free(Channel *c)
402 xfree(c->remote_name); 405 xfree(c->remote_name);
403 c->remote_name = NULL; 406 c->remote_name = NULL;
404 } 407 }
408 while ((cc = TAILQ_FIRST(&c->status_confirms)) != NULL) {
409 if (cc->abandon_cb != NULL)
410 cc->abandon_cb(c, cc->ctx);
411 TAILQ_REMOVE(&c->status_confirms, cc, entry);
412 bzero(cc, sizeof(*cc));
413 xfree(cc);
414 }
405 channels[c->self] = NULL; 415 channels[c->self] = NULL;
406 xfree(c); 416 xfree(c);
407} 417}
@@ -660,16 +670,33 @@ channel_request_start(int id, char *service, int wantconfirm)
660} 670}
661 671
662void 672void
663channel_register_confirm(int id, channel_callback_fn *fn, void *ctx) 673channel_register_status_confirm(int id, channel_confirm_cb *cb,
674 channel_confirm_abandon_cb *abandon_cb, void *ctx)
675{
676 struct channel_confirm *cc;
677 Channel *c;
678
679 if ((c = channel_lookup(id)) == NULL)
680 fatal("channel_register_expect: %d: bad id", id);
681
682 cc = xmalloc(sizeof(*cc));
683 cc->cb = cb;
684 cc->abandon_cb = abandon_cb;
685 cc->ctx = ctx;
686 TAILQ_INSERT_TAIL(&c->status_confirms, cc, entry);
687}
688
689void
690channel_register_open_confirm(int id, channel_callback_fn *fn, void *ctx)
664{ 691{
665 Channel *c = channel_lookup(id); 692 Channel *c = channel_lookup(id);
666 693
667 if (c == NULL) { 694 if (c == NULL) {
668 logit("channel_register_comfirm: %d: bad id", id); 695 logit("channel_register_open_comfirm: %d: bad id", id);
669 return; 696 return;
670 } 697 }
671 c->confirm = fn; 698 c->open_confirm = fn;
672 c->confirm_ctx = ctx; 699 c->open_confirm_ctx = ctx;
673} 700}
674 701
675void 702void
@@ -2209,9 +2236,9 @@ channel_input_open_confirmation(int type, u_int32_t seq, void *ctxt)
2209 if (compat20) { 2236 if (compat20) {
2210 c->remote_window = packet_get_int(); 2237 c->remote_window = packet_get_int();
2211 c->remote_maxpacket = packet_get_int(); 2238 c->remote_maxpacket = packet_get_int();
2212 if (c->confirm) { 2239 if (c->open_confirm) {
2213 debug2("callback start"); 2240 debug2("callback start");
2214 c->confirm(c->self, c->confirm_ctx); 2241 c->open_confirm(c->self, c->open_confirm_ctx);
2215 debug2("callback done"); 2242 debug2("callback done");
2216 } 2243 }
2217 debug2("channel %d: open confirm rwindow %u rmax %u", c->self, 2244 debug2("channel %d: open confirm rwindow %u rmax %u", c->self,
@@ -2328,6 +2355,34 @@ channel_input_port_open(int type, u_int32_t seq, void *ctxt)
2328 xfree(host); 2355 xfree(host);
2329} 2356}
2330 2357
2358/* ARGSUSED */
2359void
2360channel_input_status_confirm(int type, u_int32_t seq, void *ctxt)
2361{
2362 Channel *c;
2363 struct channel_confirm *cc;
2364 int remote_id;
2365
2366 /* Reset keepalive timeout */
2367 keep_alive_timeouts = 0;
2368
2369 remote_id = packet_get_int();
2370 packet_check_eom();
2371
2372 debug2("channel_input_confirm: type %d id %d", type, remote_id);
2373
2374 if ((c = channel_lookup(remote_id)) == NULL) {
2375 logit("channel_input_success_failure: %d: unknown", remote_id);
2376 return;
2377 }
2378 ;
2379 if ((cc = TAILQ_FIRST(&c->status_confirms)) == NULL)
2380 return;
2381 cc->cb(type, c, cc->ctx);
2382 TAILQ_REMOVE(&c->status_confirms, cc, entry);
2383 bzero(cc, sizeof(*cc));
2384 xfree(cc);
2385}
2331 2386
2332/* -- tcp forwarding */ 2387/* -- tcp forwarding */
2333 2388