[BACK]Return to channels.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Diff for /src/usr.bin/ssh/channels.c between version 1.275 and 1.276

version 1.275, 2008/05/08 12:02:23 version 1.276, 2008/05/09 04:55:56
Line 161 
Line 161 
 /* helper */  /* helper */
 static void port_open_helper(Channel *c, char *rtype);  static void port_open_helper(Channel *c, char *rtype);
   
   /* non-blocking connect helpers */
   static int connect_next(struct channel_connect *);
   static void channel_connect_ctx_free(struct channel_connect *);
   
 /* -- channel core */  /* -- channel core */
   
 Channel *  Channel *
Line 1420 
Line 1424 
 static void  static void
 channel_post_connecting(Channel *c, fd_set *readset, fd_set *writeset)  channel_post_connecting(Channel *c, fd_set *readset, fd_set *writeset)
 {  {
         int err = 0;          int err = 0, sock;
         socklen_t sz = sizeof(err);          socklen_t sz = sizeof(err);
   
         if (FD_ISSET(c->sock, writeset)) {          if (FD_ISSET(c->sock, writeset)) {
Line 1429 
Line 1433 
                         error("getsockopt SO_ERROR failed");                          error("getsockopt SO_ERROR failed");
                 }                  }
                 if (err == 0) {                  if (err == 0) {
                         debug("channel %d: connected", c->self);                          debug("channel %d: connected to %s port %d",
                               c->self, c->connect_ctx.host, c->connect_ctx.port);
                           channel_connect_ctx_free(&c->connect_ctx);
                         c->type = SSH_CHANNEL_OPEN;                          c->type = SSH_CHANNEL_OPEN;
                         if (compat20) {                          if (compat20) {
                                 packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);                                  packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
Line 1443 
Line 1449 
                                 packet_put_int(c->self);                                  packet_put_int(c->self);
                         }                          }
                 } else {                  } else {
                         debug("channel %d: not connected: %s",                          debug("channel %d: connection failed: %s",
                             c->self, strerror(err));                              c->self, strerror(err));
                           /* Try next address, if any */
                           if ((sock = connect_next(&c->connect_ctx)) > 0) {
                                   close(c->sock);
                                   c->sock = c->rfd = c->wfd = sock;
                                   channel_max_fd = channel_find_maxfd();
                                   return;
                           }
                           /* Exhausted all addresses */
                           error("connect_to %.100s port %d: failed.",
                               c->connect_ctx.host, c->connect_ctx.port);
                           channel_connect_ctx_free(&c->connect_ctx);
                         if (compat20) {                          if (compat20) {
                                 packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);                                  packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
                                 packet_put_int(c->remote_id);                                  packet_put_int(c->remote_id);
Line 2310 
Line 2327 
         Channel *c = NULL;          Channel *c = NULL;
         u_short host_port;          u_short host_port;
         char *host, *originator_string;          char *host, *originator_string;
         int remote_id, sock = -1;          int remote_id;
   
         remote_id = packet_get_int();          remote_id = packet_get_int();
         host = packet_get_string(NULL);          host = packet_get_string(NULL);
Line 2322 
Line 2339 
                 originator_string = xstrdup("unknown (remote did not supply name)");                  originator_string = xstrdup("unknown (remote did not supply name)");
         }          }
         packet_check_eom();          packet_check_eom();
         sock = channel_connect_to(host, host_port);          c = channel_connect_to(host, host_port,
         if (sock != -1) {              "connected socket", originator_string);
                 c = channel_new("connected socket",  
                     SSH_CHANNEL_CONNECTING, sock, sock, -1, 0, 0, 0,  
                     originator_string, 1);  
                 c->remote_id = remote_id;  
         }  
         xfree(originator_string);          xfree(originator_string);
           xfree(host);
         if (c == NULL) {          if (c == NULL) {
                 packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);                  packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
                 packet_put_int(remote_id);                  packet_put_int(remote_id);
                 packet_send();                  packet_send();
         }          } else
         xfree(host);                  c->remote_id = remote_id;
 }  }
   
 /* ARGSUSED */  /* ARGSUSED */
Line 2747 
Line 2760 
         num_adm_permitted_opens = 0;          num_adm_permitted_opens = 0;
 }  }
   
 /* return socket to remote host, port */  /* Try to start non-blocking connect to next host in cctx list */
 static int  static int
 connect_to(const char *host, u_short port)  connect_next(struct channel_connect *cctx)
 {  {
         struct addrinfo hints, *ai, *aitop;          int sock, saved_errno;
         char ntop[NI_MAXHOST], strport[NI_MAXSERV];          char ntop[NI_MAXHOST], strport[NI_MAXSERV];
         int gaierr;  
         int sock = -1;  
   
         memset(&hints, 0, sizeof(hints));          for (; cctx->ai; cctx->ai = cctx->ai->ai_next) {
         hints.ai_family = IPv4or6;                  if (cctx->ai->ai_family != AF_INET &&
         hints.ai_socktype = SOCK_STREAM;                      cctx->ai->ai_family != AF_INET6)
         snprintf(strport, sizeof strport, "%d", port);  
         if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) {  
                 error("connect_to %.100s: unknown host (%s)", host,  
                     ssh_gai_strerror(gaierr));  
                 return -1;  
         }  
         for (ai = aitop; ai; ai = ai->ai_next) {  
                 if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)  
                         continue;                          continue;
                 if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),                  if (getnameinfo(cctx->ai->ai_addr, cctx->ai->ai_addrlen,
                     strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) {                      ntop, sizeof(ntop), strport, sizeof(strport),
                         error("connect_to: getnameinfo failed");                      NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
                           error("connect_next: getnameinfo failed");
                         continue;                          continue;
                 }                  }
                 sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);                  if ((sock = socket(cctx->ai->ai_family, cctx->ai->ai_socktype,
                 if (sock < 0) {                      cctx->ai->ai_protocol)) == -1) {
                         if (ai->ai_next == NULL)                          if (cctx->ai->ai_next == NULL)
                                 error("socket: %.100s", strerror(errno));                                  error("socket: %.100s", strerror(errno));
                         else                          else
                                 verbose("socket: %.100s", strerror(errno));                                  verbose("socket: %.100s", strerror(errno));
Line 2783 
Line 2787 
                 }                  }
                 if (set_nonblock(sock) == -1)                  if (set_nonblock(sock) == -1)
                         fatal("%s: set_nonblock(%d)", __func__, sock);                          fatal("%s: set_nonblock(%d)", __func__, sock);
                 if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0 &&                  if (connect(sock, cctx->ai->ai_addr,
                     errno != EINPROGRESS) {                      cctx->ai->ai_addrlen) == -1 && errno != EINPROGRESS) {
                         error("connect_to %.100s port %s: %.100s", ntop, strport,                          debug("connect_next: host %.100s ([%.100s]:%s): "
                               "%.100s", cctx->host, ntop, strport,
                             strerror(errno));                              strerror(errno));
                           saved_errno = errno;
                         close(sock);                          close(sock);
                           errno = saved_errno;
                         continue;       /* fail -- try next */                          continue;       /* fail -- try next */
                 }                  }
                 break; /* success */                  debug("connect_next: host %.100s ([%.100s]:%s) "
                       "in progress, fd=%d", cctx->host, ntop, strport, sock);
                   cctx->ai = cctx->ai->ai_next;
                   set_nodelay(sock);
                   return sock;
           }
           return -1;
   }
   
   static void
   channel_connect_ctx_free(struct channel_connect *cctx)
   {
           xfree(cctx->host);
           if (cctx->aitop)
                   freeaddrinfo(cctx->aitop);
           bzero(cctx, sizeof(*cctx));
           cctx->host = NULL;
           cctx->ai = cctx->aitop = NULL;
   }
   
   /* Return CONNECTING channel to remote host, port */
   static Channel *
   connect_to(const char *host, u_short port, char *ctype, char *rname)
   {
           struct addrinfo hints;
           int gaierr;
           int sock = -1;
           char strport[NI_MAXSERV];
           struct channel_connect cctx;
           Channel *c;
   
           memset(&hints, 0, sizeof(hints));
           hints.ai_family = IPv4or6;
           hints.ai_socktype = SOCK_STREAM;
           snprintf(strport, sizeof strport, "%d", port);
           if ((gaierr = getaddrinfo(host, strport, &hints, &cctx.aitop)) != 0) {
                   error("connect_to %.100s: unknown host (%s)", host,
                       ssh_gai_strerror(gaierr));
                   return NULL;
         }          }
         freeaddrinfo(aitop);  
         if (!ai) {          cctx.host = xstrdup(host);
                 error("connect_to %.100s port %d: failed.", host, port);          cctx.port = port;
                 return -1;          cctx.ai = cctx.aitop;
   
           if ((sock = connect_next(&cctx)) == -1) {
                   error("connect to %.100s port %d failed: %s",
                       host, port, strerror(errno));
                   channel_connect_ctx_free(&cctx);
                   return NULL;
         }          }
         /* success */          c = channel_new(ctype, SSH_CHANNEL_CONNECTING, sock, sock, -1,
         set_nodelay(sock);              CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, rname, 1);
         return sock;          c->connect_ctx = cctx;
           return c;
 }  }
   
 int  Channel *
 channel_connect_by_listen_address(u_short listen_port)  channel_connect_by_listen_address(u_short listen_port, char *ctype, char *rname)
 {  {
         int i;          int i;
   
         for (i = 0; i < num_permitted_opens; i++)          for (i = 0; i < num_permitted_opens; i++) {
                 if (permitted_opens[i].host_to_connect != NULL &&                  if (permitted_opens[i].host_to_connect != NULL &&
                     permitted_opens[i].listen_port == listen_port)                      permitted_opens[i].listen_port == listen_port) {
                         return connect_to(                          return connect_to(
                             permitted_opens[i].host_to_connect,                              permitted_opens[i].host_to_connect,
                             permitted_opens[i].port_to_connect);                              permitted_opens[i].port_to_connect, ctype, rname);
                   }
           }
         error("WARNING: Server requests forwarding for unknown listen_port %d",          error("WARNING: Server requests forwarding for unknown listen_port %d",
             listen_port);              listen_port);
         return -1;          return NULL;
 }  }
   
 /* Check if connecting to that port is permitted and connect. */  /* Check if connecting to that port is permitted and connect. */
 int  Channel *
 channel_connect_to(const char *host, u_short port)  channel_connect_to(const char *host, u_short port, char *ctype, char *rname)
 {  {
         int i, permit, permit_adm = 1;          int i, permit, permit_adm = 1;
   
Line 2847 
Line 2900 
         if (!permit || !permit_adm) {          if (!permit || !permit_adm) {
                 logit("Received request to connect to host %.100s port %d, "                  logit("Received request to connect to host %.100s port %d, "
                     "but the request was denied.", host, port);                      "but the request was denied.", host, port);
                 return -1;                  return NULL;
         }          }
         return connect_to(host, port);          return connect_to(host, port, ctype, rname);
 }  }
   
 void  void

Legend:
Removed from v.1.275  
changed lines
  Added in v.1.276