]> andersk Git - openssh.git/blobdiff - channels.c
- markus@cvs.openbsd.org 2001/01/31 13:37:24
[openssh.git] / channels.c
index 254f5df2f21666cb051a1de76adbbc05d86eeb72..354160e8fa31a9e11cd41c353470ef5d7695da28 100644 (file)
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: channels.c,v 1.80 2001/01/08 22:03:23 markus Exp $");
+RCSID("$OpenBSD: channels.c,v 1.89 2001/02/04 15:32:23 stevesk Exp $");
+
+#include <openssl/rsa.h>
+#include <openssl/dsa.h>
 
 #include "ssh.h"
+#include "ssh1.h"
+#include "ssh2.h"
 #include "packet.h"
 #include "xmalloc.h"
 #include "buffer.h"
 #include "uidswap.h"
-#include "readconf.h"
-#include "servconf.h"
-
+#include "log.h"
+#include "misc.h"
 #include "channels.h"
 #include "nchan.h"
 #include "compat.h"
-
-#include "ssh2.h"
-
-#include <openssl/rsa.h>
-#include <openssl/dsa.h>
+#include "canohost.h"
 #include "key.h"
 #include "authfd.h"
 
@@ -84,7 +84,7 @@ static int channels_alloc = 0;
  * Maximum file descriptor value used in any of the channels.  This is
  * updated in channel_allocate.
  */
-static int channel_max_fd_value = 0;
+static int channel_max_fd = 0;
 
 /* Name and directory of socket for authentication agent forwarding. */
 static char *channel_forwarded_auth_socket_name = NULL;
@@ -130,6 +130,9 @@ static int all_opens_permitted = 0;
 /* This is set to true if both sides support SSH_PROTOFLAG_HOST_IN_FWD_OPEN. */
 static int have_hostname_in_open = 0;
 
+/* AF_UNSPEC or AF_INET or AF_INET6 */
+extern int IPv4or6;
+
 /* Sets specific protocol options. */
 
 void
@@ -178,12 +181,10 @@ channel_register_fds(Channel *c, int rfd, int wfd, int efd,
     int extusage, int nonblock)
 {
        /* Update the maximum file descriptor value. */
-       if (rfd > channel_max_fd_value)
-               channel_max_fd_value = rfd;
-       if (wfd > channel_max_fd_value)
-               channel_max_fd_value = wfd;
-       if (efd > channel_max_fd_value)
-               channel_max_fd_value = efd;
+       channel_max_fd = MAX(channel_max_fd, rfd);
+       channel_max_fd = MAX(channel_max_fd, wfd);
+       channel_max_fd = MAX(channel_max_fd, efd);
+
        /* XXX set close-on-exec -markus */
 
        c->rfd = rfd;
@@ -545,7 +546,7 @@ channel_post_x11_listener(Channel *c, fd_set * readset, fd_set * writeset)
        struct sockaddr addr;
        int newsock, newch;
        socklen_t addrlen;
-       char buf[16384], *remote_hostname;
+       char buf[16384], *remote_ipaddr;
        int remote_port;
 
        if (FD_ISSET(c->sock, readset)) {
@@ -556,10 +557,10 @@ channel_post_x11_listener(Channel *c, fd_set * readset, fd_set * writeset)
                        error("accept: %.100s", strerror(errno));
                        return;
                }
-               remote_hostname = get_remote_hostname(newsock);
+               remote_ipaddr = get_peer_ipaddr(newsock);
                remote_port = get_peer_port(newsock);
                snprintf(buf, sizeof buf, "X11 connection from %.200s port %d",
-                   remote_hostname, remote_port);
+                   remote_ipaddr, remote_port);
 
                newch = channel_new("x11",
                    SSH_CHANNEL_OPENING, newsock, newsock, -1,
@@ -571,8 +572,8 @@ channel_post_x11_listener(Channel *c, fd_set * readset, fd_set * writeset)
                        packet_put_int(newch);
                        packet_put_int(c->local_window_max);
                        packet_put_int(c->local_maxpacket);
-                       /* originator host and port */
-                       packet_put_cstring(remote_hostname);
+                       /* originator ipaddr and port */
+                       packet_put_cstring(remote_ipaddr);
                        if (datafellows & SSH_BUG_X11FWD) {
                                debug("ssh2 x11 bug compat mode");
                        } else {
@@ -586,7 +587,7 @@ channel_post_x11_listener(Channel *c, fd_set * readset, fd_set * writeset)
                                packet_put_string(buf, strlen(buf));
                        packet_send();
                }
-               xfree(remote_hostname);
+               xfree(remote_ipaddr);
        }
 }
 
@@ -599,7 +600,7 @@ channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset)
        struct sockaddr addr;
        int newsock, newch;
        socklen_t addrlen;
-       char buf[1024], *remote_hostname, *rtype;
+       char buf[1024], *remote_ipaddr, *rtype;
        int remote_port;
 
        rtype = (c->type == SSH_CHANNEL_RPORT_LISTENER) ?
@@ -615,13 +616,13 @@ channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset)
                        error("accept: %.100s", strerror(errno));
                        return;
                }
-               remote_hostname = get_remote_hostname(newsock);
+               remote_ipaddr = get_peer_ipaddr(newsock);
                remote_port = get_peer_port(newsock);
                snprintf(buf, sizeof buf,
                    "listen port %d for %.100s port %d, "
                    "connect from %.200s port %d",
                    c->listening_port, c->path, c->host_port,
-                   remote_hostname, remote_port);
+                   remote_ipaddr, remote_port);
 
                newch = channel_new(rtype,
                    SSH_CHANNEL_OPENING, newsock, newsock, -1,
@@ -643,7 +644,7 @@ channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset)
                                packet_put_int(c->host_port);
                        }
                        /* originator host and port */
-                       packet_put_cstring(remote_hostname);
+                       packet_put_cstring(remote_ipaddr);
                        packet_put_int(remote_port);
                        packet_send();
                } else {
@@ -656,7 +657,7 @@ channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset)
                        }
                        packet_send();
                }
-               xfree(remote_hostname);
+               xfree(remote_ipaddr);
        }
 }
 
@@ -703,7 +704,7 @@ channel_post_connecting(Channel *c, fd_set * readset, fd_set * writeset)
                int err = 0;
                int sz = sizeof(err);
                c->type = SSH_CHANNEL_OPEN;
-                if (getsockopt(c->sock, SOL_SOCKET, SO_ERROR, (char *)&err, &sz) < 0) {
+               if (getsockopt(c->sock, SOL_SOCKET, SO_ERROR, (char *)&err, &sz) < 0) {
                        debug("getsockopt SO_ERROR failed");
                } else {
                        if (err == 0) {
@@ -962,9 +963,27 @@ channel_handler(chan_fn *ftab[], fd_set * readset, fd_set * writeset)
 }
 
 void
-channel_prepare_select(fd_set * readset, fd_set * writeset)
+channel_prepare_select(fd_set **readsetp, fd_set **writesetp, int *maxfdp)
 {
-       channel_handler(channel_pre, readset, writeset);
+       int n;
+       u_int sz;
+
+       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;
+       }
+       memset(*readsetp, 0, sz);
+       memset(*writesetp, 0, sz);
+
+       channel_handler(channel_pre, *readsetp, *writesetp);
 }
 
 void
@@ -973,7 +992,7 @@ channel_after_select(fd_set * readset, fd_set * writeset)
        channel_handler(channel_post, readset, writeset);
 }
 
-/* If there is data to send to the connection, send some of it now. */
+/* If there is data to send to the connection, enqueue some of it now. */
 
 void
 channel_output_poll()
@@ -1298,7 +1317,8 @@ channel_input_open_confirmation(int type, int plen, void *ctxt)
 void
 channel_input_open_failure(int type, int plen, void *ctxt)
 {
-       int id;
+       int id, reason;
+       char *msg = NULL, *lang = NULL;
        Channel *c;
 
        if (!compat20)
@@ -1311,13 +1331,18 @@ channel_input_open_failure(int type, int plen, void *ctxt)
                packet_disconnect("Received open failure for "
                    "non-opening channel %d.", id);
        if (compat20) {
-               int reason = packet_get_int();
-               char *msg  = packet_get_string(NULL);
-               char *lang  = packet_get_string(NULL);
-               log("channel_open_failure: %d: reason %d: %s", id, reason, msg);
+               reason = packet_get_int();
+               if (packet_remaining() > 0) {
+                       msg  = packet_get_string(NULL);
+                       lang = packet_get_string(NULL);
+               }
                packet_done();
-               xfree(msg);
-               xfree(lang);
+               log("channel_open_failure: %d: reason %d %s", id,
+                   reason, msg ? msg : "<no additional info>");
+               if (msg != NULL)
+                       xfree(msg);
+               if (lang != NULL)
+                       xfree(lang);
        }
        /* Free the channel.  This will also close the socket. */
        channel_free(id);
@@ -1414,14 +1439,6 @@ channel_close_all()
                        channel_close_fds(&channels[i]);
 }
 
-/* Returns the maximum file descriptor number used by the channels. */
-
-int
-channel_max_fd()
-{
-       return channel_max_fd_value;
-}
-
 /* Returns true if any channel is still open. */
 
 int
@@ -1514,11 +1531,11 @@ channel_open_message()
  * Initiate forwarding of connections to local port "port" through the secure
  * channel to host:port from remote side.
  */
-void
+int
 channel_request_local_forwarding(u_short listen_port, const char *host_to_connect,
     u_short port_to_connect, int gateway_ports)
 {
-       channel_request_forwarding(
+       return channel_request_forwarding(
            NULL, listen_port,
            host_to_connect, port_to_connect,
            gateway_ports, /*remote_fwd*/ 0);
@@ -1528,7 +1545,7 @@ channel_request_local_forwarding(u_short listen_port, const char *host_to_connec
  * If 'remote_fwd' is true we have a '-R style' listener for protocol 2
  * (SSH_CHANNEL_RPORT_LISTENER).
  */
-void
+int
 channel_request_forwarding(
     const char *listen_address, u_short listen_port,
     const char *host_to_connect, u_short port_to_connect,
@@ -1540,16 +1557,20 @@ channel_request_forwarding(
        const char *host;
        struct linger linger;
 
+       success = 0;
+
        if (remote_fwd) {
                host = listen_address;
-               ctype = SSH_CHANNEL_RPORT_LISTENER;
+               ctype = SSH_CHANNEL_RPORT_LISTENER;
        } else {
                host = host_to_connect;
                ctype  =SSH_CHANNEL_PORT_LISTENER;
        }
 
-       if (strlen(host) > sizeof(channels[0].path) - 1)
-               packet_disconnect("Forward host name too long.");
+       if (strlen(host) > sizeof(channels[0].path) - 1) {
+               error("Forward host name too long.");
+               return success;
+       }
 
        /* XXX listen_address is currently ignored */
        /*
@@ -1564,7 +1585,6 @@ channel_request_forwarding(
        if (getaddrinfo(NULL, strport, &hints, &aitop) != 0)
                packet_disconnect("getaddrinfo: fatal error");
 
-       success = 0;
        for (ai = aitop; ai; ai = ai->ai_next) {
                if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
                        continue;
@@ -1597,7 +1617,7 @@ channel_request_forwarding(
                                error("bind: %.100s", strerror(errno));
                        else
                                verbose("bind: %.100s", strerror(errno));
-                               
+
                        close(sock);
                        continue;
                }
@@ -1617,8 +1637,10 @@ channel_request_forwarding(
                success = 1;
        }
        if (success == 0)
-               packet_disconnect("cannot listen port: %d", listen_port);       /*XXX ?disconnect? */
+               error("channel_request_forwarding: cannot listen to port: %d",
+                   listen_port);
        freeaddrinfo(aitop);
+       return success;
 }
 
 /*
@@ -1751,14 +1773,14 @@ channel_connect_to(const char *host, u_short host_port)
                        error("connect %.100s port %s: %.100s", ntop, strport,
                            strerror(errno));
                        close(sock);
-                       continue;       /* fail -- try next */  
+                       continue;       /* fail -- try next */
                }
                break; /* success */
 
        }
        freeaddrinfo(aitop);
        if (!ai) {
-               error("connect %.100s port %d: failed.", host, host_port);      
+               error("connect %.100s port %d: failed.", host, host_port);
                return -1;
        }
        /* success */
@@ -1919,6 +1941,7 @@ x11_create_display_inet(int screen_number, int x11_display_offset)
                        break;
 #endif
                }
+               freeaddrinfo(aitop);
                if (num_socks > 0)
                        break;
        }
@@ -1942,7 +1965,7 @@ x11_create_display_inet(int screen_number, int x11_display_offset)
                fatal("gethostname: %.100s", strerror(errno));
 
 #ifdef IPADDR_IN_DISPLAY
-       /* 
+       /*
         * HPUX detects the local hostname in the DISPLAY variable and tries
         * to set up a shared memory connection to the server, which it
         * incorrectly supposes to be local.
@@ -1971,7 +1994,7 @@ x11_create_display_inet(int screen_number, int x11_display_offset)
                memcpy(&my_addr, he->h_addr_list[0], sizeof(struct in_addr));
 
                /* Set DISPLAY to <ip address>:screen.display */
-               snprintf(display, sizeof(display), "%.50s:%d.%d", inet_ntoa(my_addr), 
+               snprintf(display, sizeof(display), "%.50s:%d.%d", inet_ntoa(my_addr),
                         display_number, screen_number);
        }
 #else /* IPADDR_IN_DISPLAY */
@@ -2489,7 +2512,7 @@ channel_cancel_cleanup(int id)
        }
        c->dettach_user = NULL;
 }
-void   
+void
 channel_register_filter(int id, channel_filter_fn *fn)
 {
        Channel *c = channel_lookup(id);
This page took 0.06776 seconds and 4 git commands to generate.