[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.43 and 1.44

version 1.43, 2000/03/28 20:39:05 version 1.44, 2000/04/03 07:07:15
Line 13 
Line 13 
  * There is also code for initiating connection forwarding for X11 connections,   * There is also code for initiating connection forwarding for X11 connections,
  * arbitrary tcp/ip connections, and the authentication agent connection.   * arbitrary tcp/ip connections, and the authentication agent connection.
  *   *
    * SSH2 support added by Markus Friedl.
  */   */
   
 #include "includes.h"  #include "includes.h"
Line 31 
Line 32 
 #include "nchan.h"  #include "nchan.h"
 #include "compat.h"  #include "compat.h"
   
   #include "ssh2.h"
   
 /* Maximum number of fake X11 displays to try. */  /* Maximum number of fake X11 displays to try. */
 #define MAX_DISPLAYS  1000  #define MAX_DISPLAYS  1000
   
Line 165 
Line 168 
   
         /* Do initial allocation if this is the first call. */          /* Do initial allocation if this is the first call. */
         if (channels_alloc == 0) {          if (channels_alloc == 0) {
                   chan_init();
                 channels_alloc = 10;                  channels_alloc = 10;
                 channels = xmalloc(channels_alloc * sizeof(Channel));                  channels = xmalloc(channels_alloc * sizeof(Channel));
                 for (i = 0; i < channels_alloc; i++)                  for (i = 0; i < channels_alloc; i++)
Line 237 
Line 241 
         if (c == NULL)          if (c == NULL)
                 packet_disconnect("channel free: bad local channel %d", id);                  packet_disconnect("channel free: bad local channel %d", id);
         debug("channel_free: channel %d: status: %s", id, channel_open_message());          debug("channel_free: channel %d: status: %s", id, channel_open_message());
           if (c->dettach_user != NULL) {
                   debug("channel_free: channel %d: dettaching channel user", id);
                   c->dettach_user(c->self, NULL);
           }
         if (c->sock != -1) {          if (c->sock != -1) {
                 shutdown(c->sock, SHUT_RDWR);                  shutdown(c->sock, SHUT_RDWR);
                 close(c->sock);                  close(c->sock);
                   c->sock = -1;
         }          }
           if (compat20) {
                   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;
                   }
           }
         buffer_free(&c->input);          buffer_free(&c->input);
         buffer_free(&c->output);          buffer_free(&c->output);
         buffer_free(&c->extended);          buffer_free(&c->extended);
Line 296 
Line 319 
 }  }
   
 void  void
   channel_pre_open_20(Channel *c, fd_set * readset, fd_set * writeset)
   {
           if (c->istate == CHAN_INPUT_OPEN &&
               c->remote_window > 0 &&
               buffer_len(&c->input) < c->remote_window)
                   FD_SET(c->rfd, readset);
           if (c->ostate == CHAN_OUTPUT_OPEN ||
               c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
                   if (buffer_len(&c->output) > 0) {
                           FD_SET(c->wfd, writeset);
                   } else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
                           chan_obuf_empty(c);
                   }
           }
           /** XXX check close conditions, too */
           if (c->efd != -1) {
                   if (c->extended_usage == CHAN_EXTENDED_WRITE &&
                       buffer_len(&c->extended) > 0)
                           FD_SET(c->efd, writeset);
                   else if (c->extended_usage == CHAN_EXTENDED_READ &&
                       buffer_len(&c->extended) < c->remote_window)
                           FD_SET(c->efd, readset);
           }
   }
   
   void
 channel_pre_input_draining(Channel *c, fd_set * readset, fd_set * writeset)  channel_pre_input_draining(Channel *c, fd_set * readset, fd_set * writeset)
 {  {
         if (buffer_len(&c->input) == 0) {          if (buffer_len(&c->input) == 0) {
Line 483 
Line 532 
                     SSH_CHANNEL_OPENING, newsock, newsock, -1,                      SSH_CHANNEL_OPENING, newsock, newsock, -1,
                     c->local_window_max, c->local_maxpacket,                      c->local_window_max, c->local_maxpacket,
                     0, xstrdup(buf));                      0, xstrdup(buf));
                   if (compat20) {
                 packet_start(SSH_MSG_PORT_OPEN);                          packet_start(SSH2_MSG_CHANNEL_OPEN);
                 packet_put_int(newch);                          packet_put_cstring("direct-tcpip");
                 packet_put_string(c->path, strlen(c->path));                          packet_put_int(newch);
                 packet_put_int(c->host_port);                          packet_put_int(c->local_window_max);
                 if (have_hostname_in_open) {                          packet_put_int(c->local_maxpacket);
                         packet_put_string(buf, strlen(buf));                          packet_put_string(c->path, strlen(c->path));
                           packet_put_int(c->host_port);
                           packet_put_cstring(remote_hostname);
                           packet_put_int(remote_port);
                           packet_send();
                   } else {
                           packet_start(SSH_MSG_PORT_OPEN);
                           packet_put_int(newch);
                           packet_put_string(c->path, strlen(c->path));
                           packet_put_int(c->host_port);
                           if (have_hostname_in_open) {
                                   packet_put_string(buf, strlen(buf));
                           }
                           packet_send();
                 }                  }
                 packet_send();  
                 xfree(remote_hostname);                  xfree(remote_hostname);
         }          }
 }  }
Line 569 
Line 630 
                         return -1;                          return -1;
                 }                  }
                 buffer_consume(&c->output, len);                  buffer_consume(&c->output, len);
                   if (compat20 && len > 0) {
                           c->local_consumed += len;
                   }
         }          }
         return 1;          return 1;
 }  }
   int
   channel_handle_efd(Channel *c, fd_set * readset, fd_set * writeset)
   {
           char buf[16*1024];
           int len;
   
           if (c->efd != -1) {
                   if (c->extended_usage == CHAN_EXTENDED_WRITE &&
                       FD_ISSET(c->efd, writeset) &&
                       buffer_len(&c->extended) > 0) {
                           len = write(c->efd, buffer_ptr(&c->extended),
                               buffer_len(&c->extended));
                           debug("channel %d: written %d to efd %d",
                               c->self, len, c->efd);
                           if (len > 0) {
                                   buffer_consume(&c->extended, len);
                                   c->local_consumed += len;
                           }
                   } else if (c->extended_usage == CHAN_EXTENDED_READ &&
                       FD_ISSET(c->efd, readset)) {
                           len = read(c->efd, buf, sizeof(buf));
                           debug("channel %d: read %d from efd %d",
                                c->self, len, c->efd);
                           if (len > 0)
                                   buffer_append(&c->extended, buf, len);
                   }
           }
           return 1;
   }
   int
   channel_check_window(Channel *c, fd_set * readset, fd_set * writeset)
   {
           if (!(c->flags & CHAN_CLOSE_SENT) &&
               c->local_window < c->local_window_max/2 &&
               c->local_consumed > 0) {
                   packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
                   packet_put_int(c->remote_id);
                   packet_put_int(c->local_consumed);
                   packet_send();
                   debug("channel %d: window %d sent adjust %d",
                       c->self, c->local_window,
                       c->local_consumed);
                   c->local_window += c->local_consumed;
                   c->local_consumed = 0;
           }
           return 1;
   }
   
 void  void
 channel_post_open_1(Channel *c, fd_set * readset, fd_set * writeset)  channel_post_open_1(Channel *c, fd_set * readset, fd_set * writeset)
 {  {
Line 581 
Line 692 
 }  }
   
 void  void
   channel_post_open_2(Channel *c, fd_set * readset, fd_set * writeset)
   {
           channel_handle_rfd(c, readset, writeset);
           channel_handle_wfd(c, readset, writeset);
           channel_handle_efd(c, readset, writeset);
           channel_check_window(c, readset, writeset);
   }
   
   void
 channel_post_output_drain_13(Channel *c, fd_set * readset, fd_set * writeset)  channel_post_output_drain_13(Channel *c, fd_set * readset, fd_set * writeset)
 {  {
         int len;          int len;
Line 596 
Line 716 
 }  }
   
 void  void
   channel_handler_init_20(void)
   {
           channel_pre[SSH_CHANNEL_OPEN] =                 &channel_pre_open_20;
           channel_pre[SSH_CHANNEL_PORT_LISTENER] =        &channel_pre_listener;
   
           channel_post[SSH_CHANNEL_OPEN] =                &channel_post_open_2;
           channel_post[SSH_CHANNEL_PORT_LISTENER] =       &channel_post_port_listener;
   }
   
   void
 channel_handler_init_13(void)  channel_handler_init_13(void)
 {  {
         channel_pre[SSH_CHANNEL_OPEN] =                 &channel_pre_open_13;          channel_pre[SSH_CHANNEL_OPEN] =                 &channel_pre_open_13;
Line 636 
Line 766 
                 channel_pre[i] = NULL;                  channel_pre[i] = NULL;
                 channel_post[i] = NULL;                  channel_post[i] = NULL;
         }          }
         if (compat13)          if (compat20)
                   channel_handler_init_20();
           else if (compat13)
                 channel_handler_init_13();                  channel_handler_init_13();
         else          else
                 channel_handler_init_15();                  channel_handler_init_15();
Line 660 
Line 792 
                 if (ftab[c->type] == NULL)                  if (ftab[c->type] == NULL)
                         continue;                          continue;
                 (*ftab[c->type])(c, readset, writeset);                  (*ftab[c->type])(c, readset, writeset);
                 if (!compat13)                  chan_delete_if_full_closed(c);
                         chan_delete_if_full_closed(c);  
         }          }
 }  }
   
Line 700 
Line 831 
                             c->istate != CHAN_INPUT_WAIT_DRAIN)                              c->istate != CHAN_INPUT_WAIT_DRAIN)
                                 continue;                                  continue;
                 }                  }
                   if (compat20 && (c->flags & CHAN_CLOSE_SENT)) {
                           debug("channel: %d: no data after CLOSE", c->self);
                           continue;
                   }
   
                 /* Get the amount of buffered data for this channel. */                  /* Get the amount of buffered data for this channel. */
                 len = buffer_len(&c->input);                  len = buffer_len(&c->input);
                 if (len > 0) {                  if (len > 0) {
                         /* Send some data for the other side over the secure connection. */                          /* Send some data for the other side over the secure connection. */
                         if (packet_is_interactive()) {                          if (compat20) {
                                 if (len > 1024)                                  if (len > c->remote_window)
                                         len = 512;                                          len = c->remote_window;
                                   if (len > c->remote_maxpacket)
                                           len = c->remote_maxpacket;
                         } else {                          } else {
                                 /* Keep the packets at reasonable size. */                                  if (packet_is_interactive()) {
                                 if (len > packet_get_maxsize())                                          if (len > 1024)
                                         len = packet_get_maxsize()/2;                                                  len = 512;
                                   } else {
                                           /* Keep the packets at reasonable size. */
                                           if (len > packet_get_maxsize()/2)
                                                   len = packet_get_maxsize()/2;
                                   }
                         }                          }
                         if (len > 0) {                          if (len > 0) {
                                 packet_start(SSH_MSG_CHANNEL_DATA);                                  packet_start(compat20 ?
                                       SSH2_MSG_CHANNEL_DATA : SSH_MSG_CHANNEL_DATA);
                                 packet_put_int(c->remote_id);                                  packet_put_int(c->remote_id);
                                 packet_put_string(buffer_ptr(&c->input), len);                                  packet_put_string(buffer_ptr(&c->input), len);
                                 packet_send();                                  packet_send();
                                 buffer_consume(&c->input, len);                                  buffer_consume(&c->input, len);
                                 c->remote_window -= len;                                  c->remote_window -= len;
 debug("channel %d: send data len %d", c->self, len);                                  debug("channel %d: send data len %d", c->self, len);
                         }                          }
                 } else if (c->istate == CHAN_INPUT_WAIT_DRAIN) {                  } else if (c->istate == CHAN_INPUT_WAIT_DRAIN) {
                         if (compat13)                          if (compat13)
Line 731 
Line 874 
                          */                           */
                         chan_ibuf_empty(c);                          chan_ibuf_empty(c);
                 }                  }
                   /* Send extended data, i.e. stderr */
                   if (compat20 &&
                       c->remote_window > 0 &&
                       (len = buffer_len(&c->extended)) > 0 &&
                       c->extended_usage == CHAN_EXTENDED_READ) {
                           if (len > c->remote_window)
                                   len = c->remote_window;
                           if (len > c->remote_maxpacket)
                                   len = c->remote_maxpacket;
                           packet_start(SSH2_MSG_CHANNEL_EXTENDED_DATA);
                           packet_put_int(c->remote_id);
                           packet_put_int(SSH2_EXTENDED_DATA_STDERR);
                           packet_put_string(buffer_ptr(&c->extended), len);
                           packet_send();
                           buffer_consume(&c->extended, len);
                           c->remote_window -= len;
                   }
         }          }
 }  }
   
Line 766 
Line 926 
         /* Get the data. */          /* Get the data. */
         data = packet_get_string(&data_len);          data = packet_get_string(&data_len);
   
         packet_integrity_check(plen, 4 + 4 + data_len, SSH_MSG_CHANNEL_DATA);          if (compat20){
                   if (data_len > c->local_maxpacket) {
                           log("channel %d: rcvd big packet %d, maxpack %d",
                               c->self, data_len, c->local_maxpacket);
                   }
                   if (data_len > c->local_window) {
                           log("channel %d: rcvd too much data %d, win %d",
                               c->self, data_len, c->local_window);
                           xfree(data);
                           return;
                   }
                   c->local_window -= data_len;
           }else{
                   packet_integrity_check(plen, 4 + 4 + data_len, type);
           }
         buffer_append(&c->output, data, data_len);          buffer_append(&c->output, data, data_len);
         xfree(data);          xfree(data);
 }  }
   void
   channel_input_extended_data(int type, int plen)
   {
           int id;
           int tcode;
           char *data;
           unsigned int data_len;
           Channel *c;
   
           /* Get the channel number and verify it. */
           id = packet_get_int();
           c = channel_lookup(id);
   
           if (c == NULL)
                   packet_disconnect("Received extended_data for bad channel %d.", id);
           if (c->type != SSH_CHANNEL_OPEN) {
                   log("channel %d: ext data for non open", id);
                   return;
           }
           tcode = packet_get_int();
           if (c->efd == -1 ||
               c->extended_usage != CHAN_EXTENDED_WRITE ||
               tcode != SSH2_EXTENDED_DATA_STDERR) {
                   log("channel %d: bad ext data", c->self);
                   return;
           }
           data = packet_get_string(&data_len);
           if (data_len > c->local_window) {
                   log("channel %d: rcvd too much extended_data %d, win %d",
                       c->self, data_len, c->local_window);
                   xfree(data);
                   return;
           }
           debug("channel %d: rcvd ext data %d", c->self, data_len);
           c->local_window -= data_len;
           buffer_append(&c->extended, data, data_len);
           xfree(data);
   }
   
   
 /*  /*
  * Returns true if no channel has too much buffered data, and false if one or   * Returns true if no channel has too much buffered data, and false if one or
  * more channel is overfull.   * more channel is overfull.
Line 785 
Line 998 
         for (i = 0; i < channels_alloc; i++) {          for (i = 0; i < channels_alloc; i++) {
                 c = &channels[i];                  c = &channels[i];
                 if (c->type == SSH_CHANNEL_OPEN) {                  if (c->type == SSH_CHANNEL_OPEN) {
                         if (buffer_len(&c->input) > packet_get_maxsize()) {                          if (!compat20 && buffer_len(&c->input) > packet_get_maxsize()) {
                                 debug("channel %d: big input buffer %d",                                  debug("channel %d: big input buffer %d",
                                     c->self, buffer_len(&c->input));                                      c->self, buffer_len(&c->input));
                                 return 0;                                  return 0;
Line 886 
Line 1099 
         int id, remote_id;          int id, remote_id;
         Channel *c;          Channel *c;
   
         packet_integrity_check(plen, 4 + 4, type);          if (!compat20)
                   packet_integrity_check(plen, 4 + 4, type);
   
         id = packet_get_int();          id = packet_get_int();
         c = channel_lookup(id);          c = channel_lookup(id);
Line 898 
Line 1112 
         /* Record the remote channel number and mark that the channel is now open. */          /* Record the remote channel number and mark that the channel is now open. */
         c->remote_id = remote_id;          c->remote_id = remote_id;
         c->type = SSH_CHANNEL_OPEN;          c->type = SSH_CHANNEL_OPEN;
   
           if (compat20) {
                   c->remote_window = packet_get_int();
                   c->remote_maxpacket = packet_get_int();
                   if (c->cb_fn != NULL && c->cb_event == type) {
                           debug("callback start");
                           c->cb_fn(c->self, c->cb_arg);
                           debug("callback done");
                   }
                   debug("channel %d: open confirm rwindow %d rmax %d", c->self,
                       c->remote_window, c->remote_maxpacket);
           }
 }  }
   
 void  void
Line 906 
Line 1132 
         int id;          int id;
         Channel *c;          Channel *c;
   
         packet_integrity_check(plen, 4, type);          if (!compat20)
                   packet_integrity_check(plen, 4, type);
   
         id = packet_get_int();          id = packet_get_int();
         c = channel_lookup(id);          c = channel_lookup(id);
Line 914 
Line 1141 
         if (c==NULL || c->type != SSH_CHANNEL_OPENING)          if (c==NULL || c->type != SSH_CHANNEL_OPENING)
                 packet_disconnect("Received open failure for "                  packet_disconnect("Received open failure for "
                     "non-opening channel %d.", id);                      "non-opening channel %d.", id);
           if (compat20) {
                   int reason = packet_get_int();
                   char *msg  = packet_get_string(NULL);
                   log("channel_open_failure: %d: reason %d: %s", id, reason, msg);
                   xfree(msg);
           }
         /* Free the channel.  This will also close the socket. */          /* Free the channel.  This will also close the socket. */
         channel_free(id);          channel_free(id);
 }  }
   
   void
   channel_input_channel_request(int type, int plen)
   {
           int id;
           Channel *c;
   
           id = packet_get_int();
           c = channel_lookup(id);
   
           if (c == NULL ||
               (c->type != SSH_CHANNEL_OPEN && c->type != SSH_CHANNEL_LARVAL))
                   packet_disconnect("Received request for "
                       "non-open channel %d.", id);
           if (c->cb_fn != NULL && c->cb_event == type) {
                   debug("callback start");
                   c->cb_fn(c->self, c->cb_arg);
                   debug("callback done");
           } else {
                   char *service = packet_get_string(NULL);
                   debug("channel: %d rcvd request for %s", c->self, service);
   debug("cb_fn %p cb_event %d", c->cb_fn , c->cb_event);
                   xfree(service);
           }
   }
   
   void
   channel_input_window_adjust(int type, int plen)
   {
           Channel *c;
           int id, adjust;
   
           if (!compat20)
                   return;
   
           /* Get the channel number and verify it. */
           id = packet_get_int();
           c = channel_lookup(id);
   
           if (c == NULL || c->type != SSH_CHANNEL_OPEN) {
                   log("Received window adjust for "
                       "non-open channel %d.", id);
                   return;
           }
           adjust = packet_get_int();
           debug("channel %d: rcvd adjust %d", id, adjust);
           c->remote_window += adjust;
   }
   
 /*  /*
  * Stops listening for channels, and removes any unix domain sockets that we   * Stops listening for channels, and removes any unix domain sockets that we
  * might have.   * might have.
Line 983 
Line 1263 
                 case SSH_CHANNEL_CLOSED:                  case SSH_CHANNEL_CLOSED:
                 case SSH_CHANNEL_AUTH_SOCKET:                  case SSH_CHANNEL_AUTH_SOCKET:
                         continue;                          continue;
                   case SSH_CHANNEL_LARVAL:
                           if (!compat20)
                                   fatal("cannot happen: SSH_CHANNEL_LARVAL");
                           continue;
                 case SSH_CHANNEL_OPENING:                  case SSH_CHANNEL_OPENING:
                 case SSH_CHANNEL_OPEN:                  case SSH_CHANNEL_OPEN:
                 case SSH_CHANNEL_X11_OPEN:                  case SSH_CHANNEL_X11_OPEN:
Line 1024 
Line 1308 
                 case SSH_CHANNEL_CLOSED:                  case SSH_CHANNEL_CLOSED:
                 case SSH_CHANNEL_AUTH_SOCKET:                  case SSH_CHANNEL_AUTH_SOCKET:
                         continue;                          continue;
                   case SSH_CHANNEL_LARVAL:
                 case SSH_CHANNEL_OPENING:                  case SSH_CHANNEL_OPENING:
                 case SSH_CHANNEL_OPEN:                  case SSH_CHANNEL_OPEN:
                 case SSH_CHANNEL_X11_OPEN:                  case SSH_CHANNEL_X11_OPEN:
Line 1152 
Line 1437 
         num_permitted_opens++;          num_permitted_opens++;
   
         /* Send the forward request to the remote side. */          /* Send the forward request to the remote side. */
         packet_start(SSH_CMSG_PORT_FORWARD_REQUEST);          if (compat20) {
         packet_put_int(port_to_connect);                  const char *address_to_bind = "0.0.0.0";
         packet_put_string(host_to_connect, strlen(host_to_connect));                  packet_start(SSH2_MSG_GLOBAL_REQUEST);
         packet_put_int(listen_port);                  packet_put_cstring("tcpip-forward");
         packet_send();                  packet_put_char(0);                     /* boolean: want reply */
         packet_write_wait();                  packet_put_cstring(address_to_bind);
         /*                  packet_put_int(listen_port);
          * Wait for response from the remote side.  It will send a disconnect          } else {
          * message on failure, and we will never see it here.                  packet_start(SSH_CMSG_PORT_FORWARD_REQUEST);
          */                  packet_put_int(port_to_connect);
         packet_read_expect(&payload_len, SSH_SMSG_SUCCESS);                  packet_put_cstring(host_to_connect);
                   packet_put_int(listen_port);
                   packet_send();
                   packet_write_wait();
                   /*
                    * Wait for response from the remote side.  It will send a disconnect
                    * message on failure, and we will never see it here.
                    */
                   packet_read_expect(&payload_len, SSH_SMSG_SUCCESS);
           }
 }  }
   
 /*  /*
Line 1781 
Line 2075 
         packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);          packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
         packet_put_int(remch);          packet_put_int(remch);
         packet_put_int(newch);          packet_put_int(newch);
           packet_send();
   }
   
   void
   channel_open(int id)
   {
           Channel *c = channel_lookup(id);
           if (c == NULL) {
                   log("channel_open: %d: bad id", id);
                   return;
           }
           packet_start(SSH2_MSG_CHANNEL_OPEN);
           packet_put_cstring(c->ctype);
           packet_put_int(c->self);
           packet_put_int(c->local_window);
           packet_put_int(c->local_maxpacket);
           packet_send();
           debug("channel open %d", id);
   }
   void
   channel_request(int id, char *service, int wantconfirm)
   {
           channel_request_start(id, service, wantconfirm);
           packet_send();
           debug("channel request %d: %s", id, service) ;
   }
   void
   channel_request_start(int id, char *service, int wantconfirm)
   {
           Channel *c = channel_lookup(id);
           if (c == NULL) {
                   log("channel_request: %d: bad id", id);
                   return;
           }
           packet_start(SSH2_MSG_CHANNEL_REQUEST);
           packet_put_int(c->remote_id);
           packet_put_cstring(service);
           packet_put_char(wantconfirm);
   }
   void
   channel_register_callback(int id, int mtype, channel_callback_fn *fn, void *arg)
   {
           Channel *c = channel_lookup(id);
           if (c == NULL) {
                   log("channel_register_callback: %d: bad id", id);
                   return;
           }
           c->cb_event = mtype;
           c->cb_fn = fn;
           c->cb_arg = arg;
   }
   void
   channel_register_cleanup(int id, channel_callback_fn *fn)
   {
           Channel *c = channel_lookup(id);
           if (c == NULL) {
                   log("channel_register_cleanup: %d: bad id", id);
                   return;
           }
           c->dettach_user = fn;
   }
   void
   channel_cancel_cleanup(int id)
   {
           Channel *c = channel_lookup(id);
           if (c == NULL) {
                   log("channel_cancel_cleanup: %d: bad id", id);
                   return;
           }
           c->dettach_user = NULL;
   }
   
   void
   channel_set_fds(int id, int rfd, int wfd, int efd, int extusage)
   {
           Channel *c = channel_lookup(id);
           if (c == NULL || c->type != SSH_CHANNEL_LARVAL)
                   fatal("channel_activate for non-larval channel %d.", id);
           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;
           c->type = SSH_CHANNEL_OPEN;
           c->rfd = rfd;
           c->wfd = wfd;
           c->efd = efd;
           c->extended_usage = extusage;
           /* XXX window size? */
           c->local_window = c->local_window_max = c->local_maxpacket/2;
           packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
           packet_put_int(c->remote_id);
           packet_put_int(c->local_window);
         packet_send();          packet_send();
 }  }

Legend:
Removed from v.1.43  
changed lines
  Added in v.1.44