]> andersk Git - openssh.git/blobdiff - channels.c
- markus@cvs.openbsd.org 2001/10/04 15:05:40
[openssh.git] / channels.c
index 937e059cc147c12095414c44f943718075074a48..758ea506da0691b1bb706488c2e229be46683325 100644 (file)
@@ -39,7 +39,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: channels.c,v 1.129 2001/06/29 18:40:28 stevesk Exp $");
+RCSID("$OpenBSD: channels.c,v 1.136 2001/10/04 15:05:40 markus Exp $");
 
 #include "ssh.h"
 #include "ssh1.h"
@@ -133,7 +133,7 @@ static char *auth_sock_name = NULL;
 static char *auth_sock_dir = NULL;
 
 /* AF_UNSPEC or AF_INET or AF_INET6 */
-extern int IPv4or6;
+static int IPv4or6 = AF_UNSPEC;
 
 /* helper */
 static void port_open_helper(Channel *c, char *rtype);
@@ -260,12 +260,44 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd,
        c->cb_fn = NULL;
        c->cb_arg = NULL;
        c->cb_event = 0;
-       c->dettach_user = NULL;
+       c->force_drain = 0;
+       c->detach_user = NULL;
        c->input_filter = NULL;
        debug("channel %d: new [%s]", found, remote_name);
        return c;
 }
 
+static int
+channel_find_maxfd(void)
+{
+       int i, max = 0;
+       Channel *c;
+
+       for (i = 0; i < channels_alloc; i++) {
+               c = channels[i];
+               if (c != NULL) {
+                       max = MAX(max, c->rfd);
+                       max = MAX(max, c->wfd);
+                       max = MAX(max, c->efd);
+               }
+       }
+       return max;
+}
+
+int
+channel_close_fd(int *fdp)
+{
+       int ret = 0, fd = *fdp;
+
+       if (fd != -1) {
+               ret = close(fd);
+               *fdp = -1;
+               if (fd == channel_max_fd)
+                       channel_max_fd = channel_find_maxfd();
+       }
+       return ret;
+}
+
 /* Close all channel fd/socket. */
 
 static void
@@ -274,22 +306,10 @@ channel_close_fds(Channel *c)
        debug3("channel_close_fds: channel %d: r %d w %d e %d",
            c->self, c->rfd, c->wfd, c->efd);
 
-       if (c->sock != -1) {
-               close(c->sock);
-               c->sock = -1;
-       }
-       if (c->rfd != -1) {
-               close(c->rfd);
-               c->rfd = -1;
-       }
-       if (c->wfd != -1) {
-               close(c->wfd);
-               c->wfd = -1;
-       }
-       if (c->efd != -1) {
-               close(c->efd);
-               c->efd = -1;
-       }
+       channel_close_fd(&c->sock);
+       channel_close_fd(&c->rfd);
+       channel_close_fd(&c->wfd);
+       channel_close_fd(&c->efd);
 }
 
 /* Free the channel and close its fd/socket. */
@@ -310,9 +330,9 @@ channel_free(Channel *c)
        debug3("channel_free: status: %s", s);
        xfree(s);
 
-       if (c->dettach_user != NULL) {
-               debug("channel_free: channel %d: dettaching channel user", c->self);
-               c->dettach_user(c->self, NULL);
+       if (c->detach_user != NULL) {
+               debug("channel_free: channel %d: detaching channel user", c->self);
+               c->detach_user(c->self, NULL);
        }
        if (c->sock != -1)
                shutdown(c->sock, SHUT_RDWR);
@@ -338,6 +358,22 @@ channel_free_all(void)
                        channel_free(channels[i]);
 }
 
+void
+channel_detach_all(void)
+{
+       int i;
+       Channel *c;
+
+       for (i = 0; i < channels_alloc; i++) {
+               c = channels[i];
+               if (c != NULL && c->detach_user != NULL) {
+                       debug("channel_detach_all: channel %d", c->self);
+                       c->detach_user(c->self, NULL);
+                       c->detach_user = NULL;
+               }
+       }
+}
+
 /*
  * Closes the sockets/fds of all channels.  This is used to close extra file
  * descriptors after a fork.
@@ -353,6 +389,32 @@ channel_close_all()
                        channel_close_fds(channels[i]);
 }
 
+/*
+ * Stop listening to channels.
+ */
+
+void
+channel_stop_listening(void)
+{
+       int i;
+       Channel *c;
+
+       for (i = 0; i < channels_alloc; i++) {
+               c = channels[i];
+               if (c != NULL) {
+                       switch (c->type) {
+                       case SSH_CHANNEL_AUTH_SOCKET:
+                       case SSH_CHANNEL_PORT_LISTENER:
+                       case SSH_CHANNEL_RPORT_LISTENER:
+                       case SSH_CHANNEL_X11_LISTENER:
+                               channel_close_fd(&c->sock);
+                               channel_free(c);
+                               break;
+                       }
+               }
+       }
+}
+
 /*
  * Returns true if no channel has too much buffered data, and false if one or
  * more channel is overfull.
@@ -367,14 +429,18 @@ channel_not_very_much_buffered_data()
        for (i = 0; i < channels_alloc; i++) {
                c = channels[i];
                if (c != NULL && c->type == SSH_CHANNEL_OPEN) {
-                       if (!compat20 && buffer_len(&c->input) > packet_get_maxsize()) {
+#if 0
+                       if (!compat20 &&
+                           buffer_len(&c->input) > packet_get_maxsize()) {
                                debug("channel %d: big input buffer %d",
                                    c->self, buffer_len(&c->input));
                                return 0;
                        }
+#endif
                        if (buffer_len(&c->output) > packet_get_maxsize()) {
-                               debug("channel %d: big output buffer %d",
-                                   c->self, buffer_len(&c->output));
+                               debug("channel %d: big output buffer %d > %d",
+                                   c->self, buffer_len(&c->output),
+                                   packet_get_maxsize());
                                return 0;
                        }
                }
@@ -579,7 +645,7 @@ channel_register_cleanup(int id, channel_callback_fn *fn)
                log("channel_register_cleanup: %d: bad id", id);
                return;
        }
-       c->dettach_user = fn;
+       c->detach_user = fn;
 }
 void
 channel_cancel_cleanup(int id)
@@ -589,7 +655,7 @@ channel_cancel_cleanup(int id)
                log("channel_cancel_cleanup: %d: bad id", id);
                return;
        }
-       c->dettach_user = NULL;
+       c->detach_user = NULL;
 }
 void
 channel_register_filter(int id, channel_filter_fn *fn)
@@ -800,7 +866,7 @@ channel_pre_x11_open_13(Channel *c, fd_set * readset, fd_set * writeset)
                log("X11 connection rejected because of wrong authentication.");
                buffer_clear(&c->input);
                buffer_clear(&c->output);
-               close(c->sock);
+               channel_close_fd(&c->sock);
                c->sock = -1;
                c->type = SSH_CHANNEL_CLOSED;
                packet_start(SSH_MSG_CHANNEL_CLOSE);
@@ -813,6 +879,9 @@ static void
 channel_pre_x11_open(Channel *c, fd_set * readset, fd_set * writeset)
 {
        int ret = x11_open_helper(&c->output);
+
+       /* c->force_drain = 1; */
+
        if (ret == 1) {
                c->type = SSH_CHANNEL_OPEN;
                if (compat20)
@@ -1227,14 +1296,17 @@ static int
 channel_handle_wfd(Channel *c, fd_set * readset, fd_set * writeset)
 {
        struct termios tio;
+       u_char *data;
+       u_int dlen;
        int len;
 
        /* Send buffered output data to the socket. */
        if (c->wfd != -1 &&
            FD_ISSET(c->wfd, writeset) &&
            buffer_len(&c->output) > 0) {
-               len = write(c->wfd, buffer_ptr(&c->output),
-                   buffer_len(&c->output));
+               data = buffer_ptr(&c->output);
+               dlen = buffer_len(&c->output);
+               len = write(c->wfd, data, dlen);
                if (len < 0 && (errno == EINTR || errno == EAGAIN))
                        return 1;
                if (len <= 0) {
@@ -1251,7 +1323,7 @@ channel_handle_wfd(Channel *c, fd_set * readset, fd_set * writeset)
                        }
                        return -1;
                }
-               if (compat20 && c->isatty) {
+               if (compat20 && c->isatty && dlen >= 1 && data[0] != '\r') {
                        if (tcgetattr(c->wfd, &tio) == 0 &&
                            !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) {
                                /*
@@ -1291,8 +1363,7 @@ channel_handle_efd(Channel *c, fd_set * readset, fd_set * writeset)
                        if (len <= 0) {
                                debug2("channel %d: closing write-efd %d",
                                    c->self, c->efd);
-                               close(c->efd);
-                               c->efd = -1;
+                               channel_close_fd(&c->efd);
                        } else {
                                buffer_consume(&c->extended, len);
                                c->local_consumed += len;
@@ -1307,8 +1378,7 @@ channel_handle_efd(Channel *c, fd_set * readset, fd_set * writeset)
                        if (len <= 0) {
                                debug2("channel %d: closing read-efd %d",
                                    c->self, c->efd);
-                               close(c->efd);
-                               c->efd = -1;
+                               channel_close_fd(&c->efd);
                        } else {
                                buffer_append(&c->extended, buf, len);
                        }
@@ -1490,7 +1560,7 @@ channel_handler(chan_fn *ftab[], fd_set * readset, fd_set * writeset)
  */
 void
 channel_prepare_select(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
-    int rekeying)
+    int *nallocp, int rekeying)
 {
        int n;
        u_int sz;
@@ -1498,15 +1568,13 @@ channel_prepare_select(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
        n = MAX(*maxfdp, channel_max_fd);
 
        sz = howmany(n+1, NFDBITS) * sizeof(fd_mask);
-       if (*readsetp == NULL || n > *maxfdp) {
-               if (*readsetp)
-                       xfree(*readsetp);
-               if (*writesetp)
-                       xfree(*writesetp);
-               *readsetp = xmalloc(sz);
-               *writesetp = xmalloc(sz);
-               *maxfdp = n;
+       /* perhaps check sz < nalloc/2 and shrink? */
+       if (*readsetp == NULL || sz > *nallocp) {
+               *readsetp = xrealloc(*readsetp, sz);
+               *writesetp = xrealloc(*writesetp, sz);
+               *nallocp = sz;
        }
+       *maxfdp = n;
        memset(*readsetp, 0, sz);
        memset(*writesetp, 0, sz);
 
@@ -1724,6 +1792,13 @@ channel_input_ieof(int type, int plen, void *ctxt)
        if (c == NULL)
                packet_disconnect("Received ieof for nonexistent channel %d.", id);
        chan_rcvd_ieof(c);
+
+       /* XXX force input close */
+       if (c->force_drain) {
+               debug("channel %d: FORCE input drain", c->self);
+               c->istate = CHAN_INPUT_WAIT_DRAIN;
+       }
+
 }
 
 void
@@ -1966,6 +2041,12 @@ channel_input_port_open(int type, int plen, void *ctxt)
 
 /* -- tcp forwarding */
 
+void
+channel_set_af(int af)
+{
+       IPv4or6 = af;
+}
+
 /*
  * Initiate forwarding of connections to local port "port" through the secure
  * channel to host:port from remote side.
@@ -2270,7 +2351,7 @@ connect_to(const char *host, u_short port)
 }
 
 int
-channel_connect_by_listen_adress(u_short listen_port)
+channel_connect_by_listen_address(u_short listen_port)
 {
        int i;
 
@@ -2612,6 +2693,7 @@ x11_input_open(int type, int plen, void *ctxt)
                        close(sock);
                } else {
                        c->remote_id = remote_id;
+                       c->force_drain = 1;
                }
        }
        if (c == NULL) {
@@ -2874,6 +2956,7 @@ auth_input_open_request(int type, int plen, void *ctxt)
                        close(sock);
                } else {
                        c->remote_id = remote_id;
+                       c->force_drain = 1;
                }
        }
        if (c == NULL) {
This page took 0.074937 seconds and 4 git commands to generate.