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

Diff for /src/usr.bin/ssh/clientloop.c between version 1.373 and 1.374

version 1.373, 2022/01/01 01:55:30 version 1.374, 2022/01/06 21:48:38
Line 70 
Line 70 
 #include <ctype.h>  #include <ctype.h>
 #include <errno.h>  #include <errno.h>
 #include <paths.h>  #include <paths.h>
   #include <poll.h>
 #include <signal.h>  #include <signal.h>
 #include <stdio.h>  #include <stdio.h>
 #include <stdlib.h>  #include <stdlib.h>
Line 481 
Line 482 
  * one of the file descriptors).   * one of the file descriptors).
  */   */
 static void  static void
 client_wait_until_can_do_something(struct ssh *ssh,  client_wait_until_can_do_something(struct ssh *ssh, struct pollfd **pfdp,
     fd_set **readsetp, fd_set **writesetp,      u_int *npfd_allocp, u_int *npfd_activep, int rekeying,
     int *maxfdp, u_int *nallocp, int rekeying)      int *conn_in_readyp, int *conn_out_readyp)
 {  {
         struct timeval tv, *tvp;          int timeout_secs, pollwait;
         int timeout_secs;  
         time_t minwait_secs = 0, now = monotime();          time_t minwait_secs = 0, now = monotime();
         int r, ret;          int r, ret;
           u_int p;
   
         /* Add any selections by the channel mechanism. */          *conn_in_readyp = *conn_out_readyp = 0;
         channel_prepare_select(ssh, readsetp, writesetp, maxfdp,  
             nallocp, &minwait_secs);  
   
         /* channel_prepare_select could have closed the last channel */          /* Prepare channel poll. First two pollfd entries are reserved */
           channel_prepare_poll(ssh, pfdp, npfd_allocp, npfd_activep, 2,
               &minwait_secs);
           if (*npfd_activep < 2)
                   fatal_f("bad npfd %u", *npfd_activep); /* shouldn't happen */
   
           /* channel_prepare_poll could have closed the last channel */
         if (session_closed && !channel_still_open(ssh) &&          if (session_closed && !channel_still_open(ssh) &&
             !ssh_packet_have_data_to_write(ssh)) {              !ssh_packet_have_data_to_write(ssh)) {
                 /* clear mask since we did not call select() */                  /* clear events since we did not call poll() */
                 memset(*readsetp, 0, *nallocp);                  for (p = 0; p < *npfd_activep; p++)
                 memset(*writesetp, 0, *nallocp);                          (*pfdp)[p].revents = 0;
                 return;                  return;
         }          }
   
         FD_SET(connection_in, *readsetp);          /* Monitor server connection on reserved pollfd entries */
           (*pfdp)[0].fd = connection_in;
           (*pfdp)[0].events = POLLIN;
           (*pfdp)[1].fd = connection_out;
           (*pfdp)[1].events = ssh_packet_have_data_to_write(ssh) ? POLLOUT : 0;
   
         /* Select server connection if have data to write to the server. */  
         if (ssh_packet_have_data_to_write(ssh))  
                 FD_SET(connection_out, *writesetp);  
   
         /*          /*
          * Wait for something to happen.  This will suspend the process until           * Wait for something to happen.  This will suspend the process until
          * some selected descriptor can be read, written, or has some other           * some polled descriptor can be read, written, or has some other
          * event pending, or a timeout expires.           * event pending, or a timeout expires.
          */           */
   
Line 531 
Line 536 
         if (minwait_secs != 0)          if (minwait_secs != 0)
                 timeout_secs = MINIMUM(timeout_secs, (int)minwait_secs);                  timeout_secs = MINIMUM(timeout_secs, (int)minwait_secs);
         if (timeout_secs == INT_MAX)          if (timeout_secs == INT_MAX)
                 tvp = NULL;                  pollwait = -1;
         else {          else if (timeout_secs >= INT_MAX / 1000)
                 tv.tv_sec = timeout_secs;                  pollwait = INT_MAX;
                 tv.tv_usec = 0;          else
                 tvp = &tv;                  pollwait = timeout_secs * 1000;
         }  
   
         ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);          ret = poll(*pfdp, *npfd_activep, pollwait);
   
         if (ret == -1) {          if (ret == -1) {
                 /*                  /*
                  * We have to clear the select masks, because we return.                   * We have to clear the events because we return.
                  * We have to return, because the mainloop checks for the flags                   * We have to return, because the mainloop checks for the flags
                  * set by the signal handlers.                   * set by the signal handlers.
                  */                   */
                 memset(*readsetp, 0, *nallocp);                  for (p = 0; p < *npfd_activep; p++)
                 memset(*writesetp, 0, *nallocp);                          (*pfdp)[p].revents = 0;
                 if (errno == EINTR)                  if (errno == EINTR)
                         return;                          return;
                 /* Note: we might still have data in the buffers. */                  /* Note: we might still have data in the buffers. */
                 if ((r = sshbuf_putf(stderr_buffer,                  if ((r = sshbuf_putf(stderr_buffer,
                     "select: %s\r\n", strerror(errno))) != 0)                      "poll: %s\r\n", strerror(errno))) != 0)
                         fatal_fr(r, "sshbuf_putf");                          fatal_fr(r, "sshbuf_putf");
                 quit_pending = 1;                  quit_pending = 1;
         } else if (options.server_alive_interval > 0 && !FD_ISSET(connection_in,                  return;
             *readsetp) && monotime() >= server_alive_time)          }
   
           *conn_in_readyp = (*pfdp)[0].revents != 0;
           *conn_out_readyp = (*pfdp)[1].revents != 0;
   
           if (options.server_alive_interval > 0 && !*conn_in_readyp &&
               monotime() >= server_alive_time) {
                 /*                  /*
                  * ServerAlive check is needed. We can't rely on the select                   * ServerAlive check is needed. We can't rely on the poll
                  * timing out since traffic on the client side such as port                   * timing out since traffic on the client side such as port
                  * forwards can keep waking it up.                   * forwards can keep waking it up.
                  */                   */
                 server_alive_check(ssh);                  server_alive_check(ssh);
           }
 }  }
   
 static void  static void
Line 591 
Line 603 
 }  }
   
 static void  static void
 client_process_net_input(struct ssh *ssh, fd_set *readset)  client_process_net_input(struct ssh *ssh)
 {  {
         char buf[8192];          char buf[8192];
         int r, len;          int r, len;
Line 600 
Line 612 
          * Read input from the server, and add any such data to the buffer of           * Read input from the server, and add any such data to the buffer of
          * the packet subsystem.           * the packet subsystem.
          */           */
         if (FD_ISSET(connection_in, readset)) {          schedule_server_alive_check();
                 schedule_server_alive_check();          /* Read as much as possible. */
                 /* Read as much as possible. */          len = read(connection_in, buf, sizeof(buf));
                 len = read(connection_in, buf, sizeof(buf));          if (len == 0) {
                 if (len == 0) {                  /* Received EOF. The remote host has closed the connection. */
                         /*                  if ((r = sshbuf_putf(stderr_buffer,
                          * Received EOF.  The remote host has closed the                      "Connection to %.300s closed by remote host.\r\n",
                          * connection.                      host)) != 0)
                          */                          fatal_fr(r, "sshbuf_putf");
                         if ((r = sshbuf_putf(stderr_buffer,                  quit_pending = 1;
                             "Connection to %.300s closed by remote host.\r\n",                  return;
                             host)) != 0)          }
                                 fatal_fr(r, "sshbuf_putf");          /*
                         quit_pending = 1;           * There is a kernel bug on Solaris that causes poll to
                         return;           * sometimes wake up even though there is no data available.
                 }           */
           if (len == -1 && (errno == EAGAIN || errno == EINTR))
                   len = 0;
   
           if (len == -1) {
                 /*                  /*
                  * There is a kernel bug on Solaris that causes select to                   * An error has encountered.  Perhaps there is a
                  * sometimes wake up even though there is no data available.                   * network problem.
                  */                   */
                 if (len == -1 && (errno == EAGAIN || errno == EINTR))                  if ((r = sshbuf_putf(stderr_buffer,
                         len = 0;                      "Read from remote host %.300s: %.100s\r\n",
                       host, strerror(errno))) != 0)
                 if (len == -1) {                          fatal_fr(r, "sshbuf_putf");
                         /*                  quit_pending = 1;
                          * An error has encountered.  Perhaps there is a                  return;
                          * network problem.  
                          */  
                         if ((r = sshbuf_putf(stderr_buffer,  
                             "Read from remote host %.300s: %.100s\r\n",  
                             host, strerror(errno))) != 0)  
                                 fatal_fr(r, "sshbuf_putf");  
                         quit_pending = 1;  
                         return;  
                 }  
                 ssh_packet_process_incoming(ssh, buf, len);  
         }          }
           ssh_packet_process_incoming(ssh, buf, len);
 }  }
   
 static void  static void
Line 1201 
Line 1208 
 client_loop(struct ssh *ssh, int have_pty, int escape_char_arg,  client_loop(struct ssh *ssh, int have_pty, int escape_char_arg,
     int ssh2_chan_id)      int ssh2_chan_id)
 {  {
         fd_set *readset = NULL, *writeset = NULL;          struct pollfd *pfd = NULL;
           u_int npfd_alloc = 0, npfd_active = 0;
         double start_time, total_time;          double start_time, total_time;
         int r, max_fd = 0, max_fd2 = 0, len;          int r, len;
         u_int64_t ibytes, obytes;          u_int64_t ibytes, obytes;
         u_int nalloc = 0;          int conn_in_ready, conn_out_ready;
   
         debug("Entering interactive session.");          debug("Entering interactive session.");
   
Line 1247 
Line 1255 
         exit_status = -1;          exit_status = -1;
         connection_in = ssh_packet_get_connection_in(ssh);          connection_in = ssh_packet_get_connection_in(ssh);
         connection_out = ssh_packet_get_connection_out(ssh);          connection_out = ssh_packet_get_connection_out(ssh);
         max_fd = MAXIMUM(connection_in, connection_out);  
   
         quit_pending = 0;          quit_pending = 0;
   
Line 1327 
Line 1334 
                  * Wait until we have something to do (something becomes                   * Wait until we have something to do (something becomes
                  * available on one of the descriptors).                   * available on one of the descriptors).
                  */                   */
                 max_fd2 = max_fd;                  client_wait_until_can_do_something(ssh, &pfd, &npfd_alloc,
                 client_wait_until_can_do_something(ssh, &readset, &writeset,                      &npfd_active, ssh_packet_is_rekeying(ssh),
                     &max_fd2, &nalloc, ssh_packet_is_rekeying(ssh));                      &conn_in_ready, &conn_out_ready);
   
                 if (quit_pending)                  if (quit_pending)
                         break;                          break;
   
                 /* Do channel operations unless rekeying in progress. */                  /* Do channel operations unless rekeying in progress. */
                 if (!ssh_packet_is_rekeying(ssh))                  if (!ssh_packet_is_rekeying(ssh))
                         channel_after_select(ssh, readset, writeset);                          channel_after_poll(ssh, pfd, npfd_active);
   
                 /* Buffer input from the connection.  */                  /* Buffer input from the connection.  */
                 client_process_net_input(ssh, readset);                  if (conn_in_ready)
                           client_process_net_input(ssh);
   
                 if (quit_pending)                  if (quit_pending)
                         break;                          break;
Line 1352 
Line 1360 
                  * Send as much buffered packet data as possible to the                   * Send as much buffered packet data as possible to the
                  * sender.                   * sender.
                  */                   */
                 if (FD_ISSET(connection_out, writeset)) {                  if (conn_out_ready) {
                         if ((r = ssh_packet_write_poll(ssh)) != 0) {                          if ((r = ssh_packet_write_poll(ssh)) != 0) {
                                 sshpkt_fatal(ssh, r,                                  sshpkt_fatal(ssh, r,
                                     "%s: ssh_packet_write_poll", __func__);                                      "%s: ssh_packet_write_poll", __func__);
Line 1371 
Line 1379 
                         }                          }
                 }                  }
         }          }
         free(readset);          free(pfd);
         free(writeset);  
   
         /* Terminate the session. */          /* Terminate the session. */
   

Legend:
Removed from v.1.373  
changed lines
  Added in v.1.374