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

Diff for /src/usr.bin/ssh/nchan.c between version 1.63 and 1.64

version 1.63, 2010/01/26 01:28:35 version 1.64, 2017/04/30 23:13:25
Line 72 
Line 72 
 /*  /*
  * ACTIONS: should never update the channel states   * ACTIONS: should never update the channel states
  */   */
 static void     chan_send_ieof1(Channel *);  
 static void     chan_send_oclose1(Channel *);  
 static void     chan_send_close2(Channel *);  
 static void     chan_send_eof2(Channel *);  static void     chan_send_eof2(Channel *);
 static void     chan_send_eow2(Channel *);  static void     chan_send_eow2(Channel *);
   
Line 94 
Line 91 
             istates[next]);              istates[next]);
         c->istate = next;          c->istate = next;
 }  }
   
 static void  static void
 chan_set_ostate(Channel *c, u_int next)  chan_set_ostate(Channel *c, u_int next)
 {  {
Line 104 
Line 102 
         c->ostate = next;          c->ostate = next;
 }  }
   
 /*  
  * SSH1 specific implementation of event functions  
  */  
   
 static void  
 chan_rcvd_oclose1(Channel *c)  
 {  
         debug2("channel %d: rcvd oclose", c->self);  
         switch (c->istate) {  
         case CHAN_INPUT_WAIT_OCLOSE:  
                 chan_set_istate(c, CHAN_INPUT_CLOSED);  
                 break;  
         case CHAN_INPUT_OPEN:  
                 chan_shutdown_read(c);  
                 chan_send_ieof1(c);  
                 chan_set_istate(c, CHAN_INPUT_CLOSED);  
                 break;  
         case CHAN_INPUT_WAIT_DRAIN:  
                 /* both local read_failed and remote write_failed  */  
                 chan_send_ieof1(c);  
                 chan_set_istate(c, CHAN_INPUT_CLOSED);  
                 break;  
         default:  
                 error("channel %d: protocol error: rcvd_oclose for istate %d",  
                     c->self, c->istate);  
                 return;  
         }  
 }  
 void  void
 chan_read_failed(Channel *c)  chan_read_failed(Channel *c)
 {  {
Line 147 
Line 117 
                 break;                  break;
         }          }
 }  }
   
 void  void
 chan_ibuf_empty(Channel *c)  chan_ibuf_empty(Channel *c)
 {  {
Line 158 
Line 129 
         }          }
         switch (c->istate) {          switch (c->istate) {
         case CHAN_INPUT_WAIT_DRAIN:          case CHAN_INPUT_WAIT_DRAIN:
                 if (compat20) {                  if (!(c->flags & (CHAN_CLOSE_SENT|CHAN_LOCAL)))
                         if (!(c->flags & (CHAN_CLOSE_SENT|CHAN_LOCAL)))                          chan_send_eof2(c);
                                 chan_send_eof2(c);                  chan_set_istate(c, CHAN_INPUT_CLOSED);
                         chan_set_istate(c, CHAN_INPUT_CLOSED);  
                 } else {  
                         chan_send_ieof1(c);  
                         chan_set_istate(c, CHAN_INPUT_WAIT_OCLOSE);  
                 }  
                 break;                  break;
         default:          default:
                 error("channel %d: chan_ibuf_empty for istate %d",                  error("channel %d: chan_ibuf_empty for istate %d",
Line 173 
Line 139 
                 break;                  break;
         }          }
 }  }
 static void  
 chan_rcvd_ieof1(Channel *c)  
 {  
         debug2("channel %d: rcvd ieof", c->self);  
         switch (c->ostate) {  
         case CHAN_OUTPUT_OPEN:  
                 chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);  
                 break;  
         case CHAN_OUTPUT_WAIT_IEOF:  
                 chan_set_ostate(c, CHAN_OUTPUT_CLOSED);  
                 break;  
         default:  
                 error("channel %d: protocol error: rcvd_ieof for ostate %d",  
                     c->self, c->ostate);  
                 break;  
         }  
 }  
 static void  
 chan_write_failed1(Channel *c)  
 {  
         debug2("channel %d: write failed", c->self);  
         switch (c->ostate) {  
         case CHAN_OUTPUT_OPEN:  
                 chan_shutdown_write(c);  
                 chan_send_oclose1(c);  
                 chan_set_ostate(c, CHAN_OUTPUT_WAIT_IEOF);  
                 break;  
         case CHAN_OUTPUT_WAIT_DRAIN:  
                 chan_shutdown_write(c);  
                 chan_send_oclose1(c);  
                 chan_set_ostate(c, CHAN_OUTPUT_CLOSED);  
                 break;  
         default:  
                 error("channel %d: chan_write_failed for ostate %d",  
                     c->self, c->ostate);  
                 break;  
         }  
 }  
 void  void
 chan_obuf_empty(Channel *c)  chan_obuf_empty(Channel *c)
 {  {
Line 223 
Line 152 
         switch (c->ostate) {          switch (c->ostate) {
         case CHAN_OUTPUT_WAIT_DRAIN:          case CHAN_OUTPUT_WAIT_DRAIN:
                 chan_shutdown_write(c);                  chan_shutdown_write(c);
                 if (!compat20)  
                         chan_send_oclose1(c);  
                 chan_set_ostate(c, CHAN_OUTPUT_CLOSED);                  chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
                 break;                  break;
         default:          default:
Line 233 
Line 160 
                 break;                  break;
         }          }
 }  }
 static void  
 chan_send_ieof1(Channel *c)  
 {  
         debug2("channel %d: send ieof", c->self);  
         switch (c->istate) {  
         case CHAN_INPUT_OPEN:  
         case CHAN_INPUT_WAIT_DRAIN:  
                 packet_start(SSH_MSG_CHANNEL_INPUT_EOF);  
                 packet_put_int(c->remote_id);  
                 packet_send();  
                 break;  
         default:  
                 error("channel %d: cannot send ieof for istate %d",  
                     c->self, c->istate);  
                 break;  
         }  
 }  
 static void  
 chan_send_oclose1(Channel *c)  
 {  
         debug2("channel %d: send oclose", c->self);  
         switch (c->ostate) {  
         case CHAN_OUTPUT_OPEN:  
         case CHAN_OUTPUT_WAIT_DRAIN:  
                 buffer_clear(&c->output);  
                 packet_start(SSH_MSG_CHANNEL_OUTPUT_CLOSE);  
                 packet_put_int(c->remote_id);  
                 packet_send();  
                 break;  
         default:  
                 error("channel %d: cannot send oclose for ostate %d",  
                     c->self, c->ostate);  
                 break;  
         }  
 }  
   
 /*  
  * the same for SSH2  
  */  
 static void  
 chan_rcvd_close2(Channel *c)  
 {  
         debug2("channel %d: rcvd close", c->self);  
         if (!(c->flags & CHAN_LOCAL)) {  
                 if (c->flags & CHAN_CLOSE_RCVD)  
                         error("channel %d: protocol error: close rcvd twice",  
                             c->self);  
                 c->flags |= CHAN_CLOSE_RCVD;  
         }  
         if (c->type == SSH_CHANNEL_LARVAL) {  
                 /* tear down larval channels immediately */  
                 chan_set_ostate(c, CHAN_OUTPUT_CLOSED);  
                 chan_set_istate(c, CHAN_INPUT_CLOSED);  
                 return;  
         }  
         switch (c->ostate) {  
         case CHAN_OUTPUT_OPEN:  
                 /*  
                  * wait until a data from the channel is consumed if a CLOSE  
                  * is received  
                  */  
                 chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);  
                 break;  
         }  
         switch (c->istate) {  
         case CHAN_INPUT_OPEN:  
                 chan_shutdown_read(c);  
                 chan_set_istate(c, CHAN_INPUT_CLOSED);  
                 break;  
         case CHAN_INPUT_WAIT_DRAIN:  
                 if (!(c->flags & CHAN_LOCAL))  
                         chan_send_eof2(c);  
                 chan_set_istate(c, CHAN_INPUT_CLOSED);  
                 break;  
         }  
 }  
   
 void  void
 chan_rcvd_eow(Channel *c)  chan_rcvd_eow(Channel *c)
 {  {
Line 321 
Line 172 
                 break;                  break;
         }          }
 }  }
   
 static void  static void
 chan_rcvd_eof2(Channel *c)  
 {  
         debug2("channel %d: rcvd eof", c->self);  
         c->flags |= CHAN_EOF_RCVD;  
         if (c->ostate == CHAN_OUTPUT_OPEN)  
                 chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);  
 }  
 static void  
 chan_write_failed2(Channel *c)  
 {  
         debug2("channel %d: write failed", c->self);  
         switch (c->ostate) {  
         case CHAN_OUTPUT_OPEN:  
         case CHAN_OUTPUT_WAIT_DRAIN:  
                 chan_shutdown_write(c);  
                 if (strcmp(c->ctype, "session") == 0)  
                         chan_send_eow2(c);  
                 chan_set_ostate(c, CHAN_OUTPUT_CLOSED);  
                 break;  
         default:  
                 error("channel %d: chan_write_failed for ostate %d",  
                     c->self, c->ostate);  
                 break;  
         }  
 }  
 static void  
 chan_send_eof2(Channel *c)  chan_send_eof2(Channel *c)
 {  {
         debug2("channel %d: send eof", c->self);          debug2("channel %d: send eof", c->self);
Line 364 
Line 190 
                 break;                  break;
         }          }
 }  }
   
 static void  static void
 chan_send_close2(Channel *c)  chan_send_close2(Channel *c)
 {  {
Line 381 
Line 208 
                 c->flags |= CHAN_CLOSE_SENT;                  c->flags |= CHAN_CLOSE_SENT;
         }          }
 }  }
   
 static void  static void
 chan_send_eow2(Channel *c)  chan_send_eow2(Channel *c)
 {  {
Line 404 
Line 232 
 void  void
 chan_rcvd_ieof(Channel *c)  chan_rcvd_ieof(Channel *c)
 {  {
         if (compat20)          debug2("channel %d: rcvd eof", c->self);
                 chan_rcvd_eof2(c);          c->flags |= CHAN_EOF_RCVD;
         else          if (c->ostate == CHAN_OUTPUT_OPEN)
                 chan_rcvd_ieof1(c);                  chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
         if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN &&          if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN &&
             buffer_len(&c->output) == 0 &&              buffer_len(&c->output) == 0 &&
             !CHANNEL_EFD_OUTPUT_ACTIVE(c))              !CHANNEL_EFD_OUTPUT_ACTIVE(c))
                 chan_obuf_empty(c);                  chan_obuf_empty(c);
 }  }
   
 void  void
 chan_rcvd_oclose(Channel *c)  chan_rcvd_oclose(Channel *c)
 {  {
         if (compat20)          debug2("channel %d: rcvd close", c->self);
                 chan_rcvd_close2(c);          if (!(c->flags & CHAN_LOCAL)) {
         else                  if (c->flags & CHAN_CLOSE_RCVD)
                 chan_rcvd_oclose1(c);                          error("channel %d: protocol error: close rcvd twice",
                               c->self);
                   c->flags |= CHAN_CLOSE_RCVD;
           }
           if (c->type == SSH_CHANNEL_LARVAL) {
                   /* tear down larval channels immediately */
                   chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
                   chan_set_istate(c, CHAN_INPUT_CLOSED);
                   return;
           }
           switch (c->ostate) {
           case CHAN_OUTPUT_OPEN:
                   /*
                    * wait until a data from the channel is consumed if a CLOSE
                    * is received
                    */
                   chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
                   break;
           }
           switch (c->istate) {
           case CHAN_INPUT_OPEN:
                   chan_shutdown_read(c);
                   chan_set_istate(c, CHAN_INPUT_CLOSED);
                   break;
           case CHAN_INPUT_WAIT_DRAIN:
                   if (!(c->flags & CHAN_LOCAL))
                           chan_send_eof2(c);
                   chan_set_istate(c, CHAN_INPUT_CLOSED);
                   break;
           }
 }  }
   
 void  void
 chan_write_failed(Channel *c)  chan_write_failed(Channel *c)
 {  {
         if (compat20)          debug2("channel %d: write failed", c->self);
                 chan_write_failed2(c);          switch (c->ostate) {
         else          case CHAN_OUTPUT_OPEN:
                 chan_write_failed1(c);          case CHAN_OUTPUT_WAIT_DRAIN:
                   chan_shutdown_write(c);
                   if (strcmp(c->ctype, "session") == 0)
                           chan_send_eow2(c);
                   chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
                   break;
           default:
                   error("channel %d: chan_write_failed for ostate %d",
                       c->self, c->ostate);
                   break;
           }
 }  }
   
 void  void
Line 445 
Line 314 
         }          }
         if (c->istate != CHAN_INPUT_CLOSED || c->ostate != CHAN_OUTPUT_CLOSED)          if (c->istate != CHAN_INPUT_CLOSED || c->ostate != CHAN_OUTPUT_CLOSED)
                 return 0;                  return 0;
         if (!compat20) {  
                 debug2("channel %d: is dead", c->self);  
                 return 1;  
         }  
         if ((datafellows & SSH_BUG_EXTEOF) &&          if ((datafellows & SSH_BUG_EXTEOF) &&
             c->extended_usage == CHAN_EXTENDED_WRITE &&              c->extended_usage == CHAN_EXTENDED_WRITE &&
             c->efd != -1 &&              c->efd != -1 &&
Line 486 
Line 351 
 chan_shutdown_write(Channel *c)  chan_shutdown_write(Channel *c)
 {  {
         buffer_clear(&c->output);          buffer_clear(&c->output);
         if (compat20 && c->type == SSH_CHANNEL_LARVAL)          if (c->type == SSH_CHANNEL_LARVAL)
                 return;                  return;
         /* shutdown failure is allowed if write failed already */          /* shutdown failure is allowed if write failed already */
         debug2("channel %d: close_write", c->self);          debug2("channel %d: close_write", c->self);
Line 502 
Line 367 
                             c->self, c->wfd, strerror(errno));                              c->self, c->wfd, strerror(errno));
         }          }
 }  }
   
 static void  static void
 chan_shutdown_read(Channel *c)  chan_shutdown_read(Channel *c)
 {  {
         if (compat20 && c->type == SSH_CHANNEL_LARVAL)          if (c->type == SSH_CHANNEL_LARVAL)
                 return;                  return;
         debug2("channel %d: close_read", c->self);          debug2("channel %d: close_read", c->self);
         if (c->sock != -1) {          if (c->sock != -1) {

Legend:
Removed from v.1.63  
changed lines
  Added in v.1.64