[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.409 and 1.410

version 1.409, 2022/01/01 01:55:30 version 1.410, 2022/01/06 21:46:23
Line 93 
Line 93 
 #define MAX_DISPLAYS  1000  #define MAX_DISPLAYS  1000
   
 /* Per-channel callback for pre/post select() actions */  /* Per-channel callback for pre/post select() actions */
 typedef void chan_fn(struct ssh *, Channel *c,  typedef void chan_fn(struct ssh *, Channel *c);
     fd_set *readset, fd_set *writeset);  
   
 /*  /*
  * Data structure for storing which hosts are permitted for forward requests.   * Data structure for storing which hosts are permitted for forward requests.
Line 1086 
Line 1085 
 }  }
   
 static void  static void
 channel_pre_listener(struct ssh *ssh, Channel *c,  channel_pre_listener(struct ssh *ssh, Channel *c)
     fd_set *readset, fd_set *writeset)  
 {  {
         FD_SET(c->sock, readset);          c->io_want = SSH_CHAN_IO_SOCK_R;
 }  }
   
 static void  static void
 channel_pre_connecting(struct ssh *ssh, Channel *c,  channel_pre_connecting(struct ssh *ssh, Channel *c)
     fd_set *readset, fd_set *writeset)  
 {  {
         debug3("channel %d: waiting for connection", c->self);          debug3("channel %d: waiting for connection", c->self);
         FD_SET(c->sock, writeset);          c->io_want = SSH_CHAN_IO_SOCK_W;
 }  }
   
 static void  static void
 channel_pre_open(struct ssh *ssh, Channel *c,  channel_pre_open(struct ssh *ssh, Channel *c)
     fd_set *readset, fd_set *writeset)  
 {  {
           c->io_want = 0;
         if (c->istate == CHAN_INPUT_OPEN &&          if (c->istate == CHAN_INPUT_OPEN &&
             c->remote_window > 0 &&              c->remote_window > 0 &&
             sshbuf_len(c->input) < c->remote_window &&              sshbuf_len(c->input) < c->remote_window &&
             sshbuf_check_reserve(c->input, CHAN_RBUF) == 0)              sshbuf_check_reserve(c->input, CHAN_RBUF) == 0)
                 FD_SET(c->rfd, readset);                  c->io_want |= SSH_CHAN_IO_RFD;
         if (c->ostate == CHAN_OUTPUT_OPEN ||          if (c->ostate == CHAN_OUTPUT_OPEN ||
             c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {              c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
                 if (sshbuf_len(c->output) > 0) {                  if (sshbuf_len(c->output) > 0) {
                         FD_SET(c->wfd, writeset);                          c->io_want |= SSH_CHAN_IO_WFD;
                 } else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {                  } else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
                         if (CHANNEL_EFD_OUTPUT_ACTIVE(c))                          if (CHANNEL_EFD_OUTPUT_ACTIVE(c))
                                 debug2("channel %d: "                                  debug2("channel %d: "
Line 1127 
Line 1124 
             c->ostate == CHAN_OUTPUT_CLOSED)) {              c->ostate == CHAN_OUTPUT_CLOSED)) {
                 if (c->extended_usage == CHAN_EXTENDED_WRITE &&                  if (c->extended_usage == CHAN_EXTENDED_WRITE &&
                     sshbuf_len(c->extended) > 0)                      sshbuf_len(c->extended) > 0)
                         FD_SET(c->efd, writeset);                          c->io_want |= SSH_CHAN_IO_EFD_W;
                 else if (c->efd != -1 && !(c->flags & CHAN_EOF_SENT) &&                  else if (c->efd != -1 && !(c->flags & CHAN_EOF_SENT) &&
                     (c->extended_usage == CHAN_EXTENDED_READ ||                      (c->extended_usage == CHAN_EXTENDED_READ ||
                     c->extended_usage == CHAN_EXTENDED_IGNORE) &&                      c->extended_usage == CHAN_EXTENDED_IGNORE) &&
                     sshbuf_len(c->extended) < c->remote_window)                      sshbuf_len(c->extended) < c->remote_window)
                         FD_SET(c->efd, readset);                          c->io_want |= SSH_CHAN_IO_EFD_R;
         }          }
         /* XXX: What about efd? races? */          /* XXX: What about efd? races? */
 }  }
Line 1214 
Line 1211 
 }  }
   
 static void  static void
 channel_pre_x11_open(struct ssh *ssh, Channel *c,  channel_pre_x11_open(struct ssh *ssh, Channel *c)
     fd_set *readset, fd_set *writeset)  
 {  {
         int ret = x11_open_helper(ssh, c->output);          int ret = x11_open_helper(ssh, c->output);
   
Line 1223 
Line 1219 
   
         if (ret == 1) {          if (ret == 1) {
                 c->type = SSH_CHANNEL_OPEN;                  c->type = SSH_CHANNEL_OPEN;
                 channel_pre_open(ssh, c, readset, writeset);                  channel_pre_open(ssh, c);
         } else if (ret == -1) {          } else if (ret == -1) {
                 logit("X11 connection rejected because of wrong authentication.");                  logit("X11 connection rejected because of wrong authentication.");
                 debug2("X11 rejected %d i%d/o%d",                  debug2("X11 rejected %d i%d/o%d",
Line 1238 
Line 1234 
 }  }
   
 static void  static void
 channel_pre_mux_client(struct ssh *ssh,  channel_pre_mux_client(struct ssh *ssh, Channel *c)
     Channel *c, fd_set *readset, fd_set *writeset)  
 {  {
           c->io_want = 0;
         if (c->istate == CHAN_INPUT_OPEN && !c->mux_pause &&          if (c->istate == CHAN_INPUT_OPEN && !c->mux_pause &&
             sshbuf_check_reserve(c->input, CHAN_RBUF) == 0)              sshbuf_check_reserve(c->input, CHAN_RBUF) == 0)
                 FD_SET(c->rfd, readset);                  c->io_want |= SSH_CHAN_IO_RFD;
         if (c->istate == CHAN_INPUT_WAIT_DRAIN) {          if (c->istate == CHAN_INPUT_WAIT_DRAIN) {
                 /* clear buffer immediately (discard any partial packet) */                  /* clear buffer immediately (discard any partial packet) */
                 sshbuf_reset(c->input);                  sshbuf_reset(c->input);
Line 1254 
Line 1250 
         if (c->ostate == CHAN_OUTPUT_OPEN ||          if (c->ostate == CHAN_OUTPUT_OPEN ||
             c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {              c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
                 if (sshbuf_len(c->output) > 0)                  if (sshbuf_len(c->output) > 0)
                         FD_SET(c->wfd, writeset);                          c->io_want |= SSH_CHAN_IO_WFD;
                 else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN)                  else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN)
                         chan_obuf_empty(ssh, c);                          chan_obuf_empty(ssh, c);
         }          }
Line 1533 
Line 1529 
   
 /* dynamic port forwarding */  /* dynamic port forwarding */
 static void  static void
 channel_pre_dynamic(struct ssh *ssh, Channel *c,  channel_pre_dynamic(struct ssh *ssh, Channel *c)
     fd_set *readset, fd_set *writeset)  
 {  {
         const u_char *p;          const u_char *p;
         u_int have;          u_int have;
         int ret;          int ret;
   
           c->io_want = 0;
         have = sshbuf_len(c->input);          have = sshbuf_len(c->input);
         debug2("channel %d: pre_dynamic: have %d", c->self, have);          debug2("channel %d: pre_dynamic: have %d", c->self, have);
         /* sshbuf_dump(c->input, stderr); */          /* sshbuf_dump(c->input, stderr); */
         /* check if the fixed size part of the packet is in buffer. */          /* check if the fixed size part of the packet is in buffer. */
         if (have < 3) {          if (have < 3) {
                 /* need more */                  /* need more */
                 FD_SET(c->sock, readset);                  c->io_want |= SSH_CHAN_IO_RFD;
                 return;                  return;
         }          }
         /* try to guess the protocol */          /* try to guess the protocol */
Line 1568 
Line 1564 
         } else if (ret == 0) {          } else if (ret == 0) {
                 debug2("channel %d: pre_dynamic: need more", c->self);                  debug2("channel %d: pre_dynamic: need more", c->self);
                 /* need more */                  /* need more */
                 FD_SET(c->sock, readset);                  c->io_want |= SSH_CHAN_IO_RFD;
                 if (sshbuf_len(c->output))                  if (sshbuf_len(c->output))
                         FD_SET(c->sock, writeset);                          c->io_want |= SSH_CHAN_IO_WFD;
         } else {          } else {
                 /* switch to the next state */                  /* switch to the next state */
                 c->type = SSH_CHANNEL_OPENING;                  c->type = SSH_CHANNEL_OPENING;
Line 1650 
Line 1646 
   
 /* This is our fake X11 server socket. */  /* This is our fake X11 server socket. */
 static void  static void
 channel_post_x11_listener(struct ssh *ssh, Channel *c,  channel_post_x11_listener(struct ssh *ssh, Channel *c)
     fd_set *readset, fd_set *writeset)  
 {  {
         Channel *nc;          Channel *nc;
         struct sockaddr_storage addr;          struct sockaddr_storage addr;
Line 1659 
Line 1654 
         socklen_t addrlen;          socklen_t addrlen;
         char buf[16384], *remote_ipaddr;          char buf[16384], *remote_ipaddr;
   
         if (!FD_ISSET(c->sock, readset))          if ((c->io_ready & SSH_CHAN_IO_SOCK_R) == 0)
                 return;                  return;
   
         debug("X11 connection requested.");          debug("X11 connection requested.");
Line 1768 
Line 1763 
  * This socket is listening for connections to a forwarded TCP/IP port.   * This socket is listening for connections to a forwarded TCP/IP port.
  */   */
 static void  static void
 channel_post_port_listener(struct ssh *ssh, Channel *c,  channel_post_port_listener(struct ssh *ssh, Channel *c)
     fd_set *readset, fd_set *writeset)  
 {  {
         Channel *nc;          Channel *nc;
         struct sockaddr_storage addr;          struct sockaddr_storage addr;
Line 1777 
Line 1771 
         socklen_t addrlen;          socklen_t addrlen;
         char *rtype;          char *rtype;
   
         if (!FD_ISSET(c->sock, readset))          if ((c->io_ready & SSH_CHAN_IO_SOCK_R) == 0)
                 return;                  return;
   
         debug("Connection to port %d forwarding to %.100s port %d requested.",          debug("Connection to port %d forwarding to %.100s port %d requested.",
Line 1828 
Line 1822 
  * clients.   * clients.
  */   */
 static void  static void
 channel_post_auth_listener(struct ssh *ssh, Channel *c,  channel_post_auth_listener(struct ssh *ssh, Channel *c)
     fd_set *readset, fd_set *writeset)  
 {  {
         Channel *nc;          Channel *nc;
         int r, newsock;          int r, newsock;
         struct sockaddr_storage addr;          struct sockaddr_storage addr;
         socklen_t addrlen;          socklen_t addrlen;
   
         if (!FD_ISSET(c->sock, readset))          if ((c->io_ready & SSH_CHAN_IO_SOCK_R) == 0)
                 return;                  return;
   
         addrlen = sizeof(addr);          addrlen = sizeof(addr);
Line 1857 
Line 1850 
 }  }
   
 static void  static void
 channel_post_connecting(struct ssh *ssh, Channel *c,  channel_post_connecting(struct ssh *ssh, Channel *c)
     fd_set *readset, fd_set *writeset)  
 {  {
         int err = 0, sock, isopen, r;          int err = 0, sock, isopen, r;
         socklen_t sz = sizeof(err);          socklen_t sz = sizeof(err);
   
         if (!FD_ISSET(c->sock, writeset))          if ((c->io_ready & SSH_CHAN_IO_SOCK_W) == 0)
                 return;                  return;
         if (!c->have_remote_id)          if (!c->have_remote_id)
                 fatal_f("channel %d: no remote id", c->self);                  fatal_f("channel %d: no remote id", c->self);
Line 1922 
Line 1914 
 }  }
   
 static int  static int
 channel_handle_rfd(struct ssh *ssh, Channel *c,  channel_handle_rfd(struct ssh *ssh, Channel *c)
     fd_set *readset, fd_set *writeset)  
 {  {
         char buf[CHAN_RBUF];          char buf[CHAN_RBUF];
         ssize_t len;          ssize_t len;
         int r;          int r;
   
         if (c->rfd == -1 || !FD_ISSET(c->rfd, readset))          if ((c->io_ready & SSH_CHAN_IO_RFD) == 0)
                 return 1;                  return 1;
   
         len = read(c->rfd, buf, sizeof(buf));          len = read(c->rfd, buf, sizeof(buf));
Line 1961 
Line 1952 
 }  }
   
 static int  static int
 channel_handle_wfd(struct ssh *ssh, Channel *c,  channel_handle_wfd(struct ssh *ssh, Channel *c)
    fd_set *readset, fd_set *writeset)  
 {  {
         struct termios tio;          struct termios tio;
         u_char *data = NULL, *buf; /* XXX const; need filter API change */          u_char *data = NULL, *buf; /* XXX const; need filter API change */
         size_t dlen, olen = 0;          size_t dlen, olen = 0;
         int r, len;          int r, len;
   
         if (c->wfd == -1 || !FD_ISSET(c->wfd, writeset) ||          if ((c->io_ready & SSH_CHAN_IO_WFD) == 0)
             sshbuf_len(c->output) == 0)  
                 return 1;                  return 1;
           if (sshbuf_len(c->output) == 0)
                   return 1;
   
         /* Send buffered output data to the socket. */          /* Send buffered output data to the socket. */
         olen = sshbuf_len(c->output);          olen = sshbuf_len(c->output);
Line 2041 
Line 2032 
 }  }
   
 static int  static int
 channel_handle_efd_write(struct ssh *ssh, Channel *c,  channel_handle_efd_write(struct ssh *ssh, Channel *c)
     fd_set *readset, fd_set *writeset)  
 {  {
         int r;          int r;
         ssize_t len;          ssize_t len;
   
         if (!FD_ISSET(c->efd, writeset) || sshbuf_len(c->extended) == 0)          if ((c->io_ready & SSH_CHAN_IO_EFD_W) == 0)
                 return 1;                  return 1;
           if (sshbuf_len(c->extended) == 0)
                   return 1;
   
         len = write(c->efd, sshbuf_ptr(c->extended),          len = write(c->efd, sshbuf_ptr(c->extended),
             sshbuf_len(c->extended));              sshbuf_len(c->extended));
Line 2067 
Line 2059 
 }  }
   
 static int  static int
 channel_handle_efd_read(struct ssh *ssh, Channel *c,  channel_handle_efd_read(struct ssh *ssh, Channel *c)
     fd_set *readset, fd_set *writeset)  
 {  {
         char buf[CHAN_RBUF];          char buf[CHAN_RBUF];
         int r;          int r;
         ssize_t len;          ssize_t len;
   
         if (!FD_ISSET(c->efd, readset))          if ((c->io_ready & SSH_CHAN_IO_EFD_R) == 0)
                 return 1;                  return 1;
   
         len = read(c->efd, buf, sizeof(buf));          len = read(c->efd, buf, sizeof(buf));
Line 2092 
Line 2083 
 }  }
   
 static int  static int
 channel_handle_efd(struct ssh *ssh, Channel *c,  channel_handle_efd(struct ssh *ssh, Channel *c)
     fd_set *readset, fd_set *writeset)  
 {  {
         if (c->efd == -1)          if (c->efd == -1)
                 return 1;                  return 1;
Line 2101 
Line 2091 
         /** XXX handle drain efd, too */          /** XXX handle drain efd, too */
   
         if (c->extended_usage == CHAN_EXTENDED_WRITE)          if (c->extended_usage == CHAN_EXTENDED_WRITE)
                 return channel_handle_efd_write(ssh, c, readset, writeset);                  return channel_handle_efd_write(ssh, c);
         else if (c->extended_usage == CHAN_EXTENDED_READ ||          else if (c->extended_usage == CHAN_EXTENDED_READ ||
             c->extended_usage == CHAN_EXTENDED_IGNORE)              c->extended_usage == CHAN_EXTENDED_IGNORE)
                 return channel_handle_efd_read(ssh, c, readset, writeset);                  return channel_handle_efd_read(ssh, c);
   
         return 1;          return 1;
 }  }
Line 2138 
Line 2128 
 }  }
   
 static void  static void
 channel_post_open(struct ssh *ssh, Channel *c,  channel_post_open(struct ssh *ssh, Channel *c)
     fd_set *readset, fd_set *writeset)  
 {  {
         channel_handle_rfd(ssh, c, readset, writeset);          channel_handle_rfd(ssh, c);
         channel_handle_wfd(ssh, c, readset, writeset);          channel_handle_wfd(ssh, c);
         channel_handle_efd(ssh, c, readset, writeset);          channel_handle_efd(ssh, c);
         channel_check_window(ssh, c);          channel_check_window(ssh, c);
 }  }
   
Line 2172 
Line 2161 
 }  }
   
 static void  static void
 channel_post_mux_client_read(struct ssh *ssh, Channel *c,  channel_post_mux_client_read(struct ssh *ssh, Channel *c)
     fd_set *readset, fd_set *writeset)  
 {  {
         u_int need;          u_int need;
   
         if (c->rfd == -1 || !FD_ISSET(c->rfd, readset))          if ((c->io_ready & SSH_CHAN_IO_RFD) == 0)
                 return;                  return;
         if (c->istate != CHAN_INPUT_OPEN && c->istate != CHAN_INPUT_WAIT_DRAIN)          if (c->istate != CHAN_INPUT_OPEN && c->istate != CHAN_INPUT_WAIT_DRAIN)
                 return;                  return;
Line 2209 
Line 2197 
 }  }
   
 static void  static void
 channel_post_mux_client_write(struct ssh *ssh, Channel *c,  channel_post_mux_client_write(struct ssh *ssh, Channel *c)
     fd_set *readset, fd_set *writeset)  
 {  {
         ssize_t len;          ssize_t len;
         int r;          int r;
   
         if (c->wfd == -1 || !FD_ISSET(c->wfd, writeset) ||          if ((c->io_ready & SSH_CHAN_IO_WFD) == 0)
             sshbuf_len(c->output) == 0)  
                 return;                  return;
           if (sshbuf_len(c->output) == 0)
                   return;
   
         len = write(c->wfd, sshbuf_ptr(c->output), sshbuf_len(c->output));          len = write(c->wfd, sshbuf_ptr(c->output), sshbuf_len(c->output));
         if (len == -1 && (errno == EINTR || errno == EAGAIN))          if (len == -1 && (errno == EINTR || errno == EAGAIN))
Line 2231 
Line 2219 
 }  }
   
 static void  static void
 channel_post_mux_client(struct ssh *ssh, Channel *c,  channel_post_mux_client(struct ssh *ssh, Channel *c)
     fd_set *readset, fd_set *writeset)  
 {  {
         channel_post_mux_client_read(ssh, c, readset, writeset);          channel_post_mux_client_read(ssh, c);
         channel_post_mux_client_write(ssh, c, readset, writeset);          channel_post_mux_client_write(ssh, c);
 }  }
   
 static void  static void
 channel_post_mux_listener(struct ssh *ssh, Channel *c,  channel_post_mux_listener(struct ssh *ssh, Channel *c)
     fd_set *readset, fd_set *writeset)  
 {  {
         Channel *nc;          Channel *nc;
         struct sockaddr_storage addr;          struct sockaddr_storage addr;
Line 2249 
Line 2235 
         uid_t euid;          uid_t euid;
         gid_t egid;          gid_t egid;
   
         if (!FD_ISSET(c->sock, readset))          if ((c->io_ready & SSH_CHAN_IO_SOCK_R) == 0)
                 return;                  return;
   
         debug("multiplexing control connection");          debug("multiplexing control connection");
Line 2355 
Line 2341 
 enum channel_table { CHAN_PRE, CHAN_POST };  enum channel_table { CHAN_PRE, CHAN_POST };
   
 static void  static void
 channel_handler(struct ssh *ssh, int table,  channel_handler(struct ssh *ssh, int table, time_t *unpause_secs)
     fd_set *readset, fd_set *writeset, time_t *unpause_secs)  
 {  {
         struct ssh_channels *sc = ssh->chanctxt;          struct ssh_channels *sc = ssh->chanctxt;
         chan_fn **ftab = table == CHAN_PRE ? sc->channel_pre : sc->channel_post;          chan_fn **ftab = table == CHAN_PRE ? sc->channel_pre : sc->channel_post;
Line 2382 
Line 2367 
                          * Run handlers that are not paused.                           * Run handlers that are not paused.
                          */                           */
                         if (c->notbefore <= now)                          if (c->notbefore <= now)
                                 (*ftab[c->type])(ssh, c, readset, writeset);                                  (*ftab[c->type])(ssh, c);
                         else if (unpause_secs != NULL) {                          else if (unpause_secs != NULL) {
                                 /*                                  /*
                                  * Collect the time that the earliest                                   * Collect the time that the earliest
Line 2432 
Line 2417 
 channel_prepare_select(struct ssh *ssh, fd_set **readsetp, fd_set **writesetp,  channel_prepare_select(struct ssh *ssh, fd_set **readsetp, fd_set **writesetp,
     int *maxfdp, u_int *nallocp, time_t *minwait_secs)      int *maxfdp, u_int *nallocp, time_t *minwait_secs)
 {  {
         u_int n, sz, nfdset;          struct ssh_channels *sc = ssh->chanctxt;
           u_int i, n, sz, nfdset, oalloc = sc->channels_alloc;
           Channel *c;
   
         channel_before_prepare_select(ssh); /* might update channel_max_fd */          channel_before_prepare_select(ssh); /* might update channel_max_fd */
   
Line 2455 
Line 2442 
         memset(*writesetp, 0, sz);          memset(*writesetp, 0, sz);
   
         if (!ssh_packet_is_rekeying(ssh))          if (!ssh_packet_is_rekeying(ssh))
                 channel_handler(ssh, CHAN_PRE, *readsetp, *writesetp,                  channel_handler(ssh, CHAN_PRE, minwait_secs);
                     minwait_secs);  
           /* Convert c->io_want into FD_SET */
           for (i = 0; i < oalloc; i++) {
                   c = sc->channels[i];
                   if (c == NULL)
                           continue;
                   if ((c->io_want & SSH_CHAN_IO_RFD) != 0) {
                           if (c->rfd == -1)
                                   fatal_f("channel %d: no rfd", c->self);
                           FD_SET(c->rfd, *readsetp);
                   }
                   if ((c->io_want & SSH_CHAN_IO_WFD) != 0) {
                           if (c->wfd == -1)
                                   fatal_f("channel %d: no wfd", c->self);
                           FD_SET(c->wfd, *writesetp);
                   }
                   if ((c->io_want & SSH_CHAN_IO_EFD_R) != 0) {
                           if (c->efd == -1)
                                   fatal_f("channel %d: no efd(r)", c->self);
                           FD_SET(c->efd, *readsetp);
                   }
                   if ((c->io_want & SSH_CHAN_IO_EFD_W) != 0) {
                           if (c->efd == -1)
                                   fatal_f("channel %d: no efd(w)", c->self);
                           FD_SET(c->efd, *writesetp);
                   }
                   if ((c->io_want & SSH_CHAN_IO_SOCK_R) != 0) {
                           if (c->sock == -1)
                                   fatal_f("channel %d: no sock(r)", c->self);
                           FD_SET(c->sock, *readsetp);
                   }
                   if ((c->io_want & SSH_CHAN_IO_SOCK_W) != 0) {
                           if (c->sock == -1)
                                   fatal_f("channel %d: no sock(w)", c->self);
                           FD_SET(c->sock, *writesetp);
                   }
           }
 }  }
   
 /*  /*
Line 2466 
Line 2489 
 void  void
 channel_after_select(struct ssh *ssh, fd_set *readset, fd_set *writeset)  channel_after_select(struct ssh *ssh, fd_set *readset, fd_set *writeset)
 {  {
         channel_handler(ssh, CHAN_POST, readset, writeset, NULL);          struct ssh_channels *sc = ssh->chanctxt;
           Channel *c;
           u_int i, oalloc = sc->channels_alloc;
   
           /* Convert FD_SET into c->io_ready */
           for (i = 0; i < oalloc; i++) {
                   c = sc->channels[i];
                   if (c == NULL)
                           continue;
                   c->io_ready = 0;
                   if (c->rfd != -1 && FD_ISSET(c->rfd, readset))
                           c->io_ready |= SSH_CHAN_IO_RFD;
                   if (c->wfd != -1 && FD_ISSET(c->wfd, writeset))
                           c->io_ready |= SSH_CHAN_IO_WFD;
                   if (c->efd != -1 && FD_ISSET(c->efd, readset))
                           c->io_ready |= SSH_CHAN_IO_EFD_R;
                   if (c->efd != -1 && FD_ISSET(c->efd, writeset))
                           c->io_ready |= SSH_CHAN_IO_EFD_W;
                   if (c->sock != -1 && FD_ISSET(c->sock, readset))
                           c->io_ready |= SSH_CHAN_IO_SOCK_R;
                   if (c->sock != -1 && FD_ISSET(c->sock, writeset))
                           c->io_ready |= SSH_CHAN_IO_SOCK_W;
           }
           channel_handler(ssh, CHAN_POST, NULL);
 }  }
   
 /*  /*

Legend:
Removed from v.1.409  
changed lines
  Added in v.1.410