[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.13 and 1.14

version 1.13, 1999/10/14 18:17:42 version 1.14, 1999/10/16 20:47:13
Line 26 
Line 26 
 #include "uidswap.h"  #include "uidswap.h"
 #include "servconf.h"  #include "servconf.h"
   
   #include "channels.h"
   #include "nchan.h"
   #include "compat.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
   
 /* Definitions for channel types. */  
 #define SSH_CHANNEL_FREE                0 /* This channel is free (unused). */  
 #define SSH_CHANNEL_X11_LISTENER        1 /* Listening for inet X11 conn. */  
 #define SSH_CHANNEL_PORT_LISTENER       2 /* Listening on a port. */  
 #define SSH_CHANNEL_OPENING             3 /* waiting for confirmation */  
 #define SSH_CHANNEL_OPEN                4 /* normal open two-way channel */  
 #define SSH_CHANNEL_CLOSED              5 /* waiting for close confirmation */  
 /*      SSH_CHANNEL_AUTH_FD             6    authentication fd */  
 #define SSH_CHANNEL_AUTH_SOCKET         7 /* authentication socket */  
 /*      SSH_CHANNEL_AUTH_SOCKET_FD      8    connection to auth socket */  
 #define SSH_CHANNEL_X11_OPEN            9 /* reading first X11 packet */  
 #define SSH_CHANNEL_INPUT_DRAINING      10 /* sending remaining data to conn */  
 #define SSH_CHANNEL_OUTPUT_DRAINING     11 /* sending remaining data to app */  
   
 /* Max len of agent socket */  /* Max len of agent socket */
 #define MAX_SOCKET_NAME 100  #define MAX_SOCKET_NAME 100
   
 /* Data structure for channel data.  This is iniailized in channel_allocate  
    and cleared in channel_free. */  
   
 typedef struct  
 {  
   int type;  
   int sock;  
   int remote_id;  
   Buffer input;  
   Buffer output;  
   char path[200]; /* path for unix domain sockets, or host name for forwards */  
   int host_port;  /* port to connect for forwards */  
   int listening_port; /* port being listened for forwards */  
   char *remote_name;  
 } Channel;  
   
 /* Pointer to an array containing all allocated channels.  The array is  /* Pointer to an array containing all allocated channels.  The array is
    dynamically extended as needed. */     dynamically extended as needed. */
 static Channel *channels = NULL;  static Channel *channels = NULL;
Line 160 
Line 134 
         /* Found a free slot.  Initialize the fields and return its number. */          /* Found a free slot.  Initialize the fields and return its number. */
         buffer_init(&channels[i].input);          buffer_init(&channels[i].input);
         buffer_init(&channels[i].output);          buffer_init(&channels[i].output);
           channels[i].self = i;
         channels[i].type = type;          channels[i].type = type;
         channels[i].sock = sock;          channels[i].sock = sock;
           channels[i].flags = 0;
         channels[i].remote_id = -1;          channels[i].remote_id = -1;
         channels[i].remote_name = remote_name;          channels[i].remote_name = remote_name;
         return i;          return i;
Line 178 
Line 154 
      available.  Initialize and return its number. */       available.  Initialize and return its number. */
   buffer_init(&channels[old_channels].input);    buffer_init(&channels[old_channels].input);
   buffer_init(&channels[old_channels].output);    buffer_init(&channels[old_channels].output);
     channels[old_channels].self = old_channels;
   channels[old_channels].type = type;    channels[old_channels].type = type;
   channels[old_channels].sock = sock;    channels[old_channels].sock = sock;
     channels[old_channels].flags = 0;
   channels[old_channels].remote_id = -1;    channels[old_channels].remote_id = -1;
   channels[old_channels].remote_name = remote_name;    channels[old_channels].remote_name = remote_name;
   return old_channels;    return old_channels;
Line 191 
Line 169 
 {  {
   assert(channel >= 0 && channel < channels_alloc &&    assert(channel >= 0 && channel < channels_alloc &&
          channels[channel].type != SSH_CHANNEL_FREE);           channels[channel].type != SSH_CHANNEL_FREE);
   shutdown(channels[channel].sock, SHUT_RDWR);    if(compat13)
       shutdown(channels[channel].sock, SHUT_RDWR);
   close(channels[channel].sock);    close(channels[channel].sock);
   buffer_free(&channels[channel].input);    buffer_free(&channels[channel].input);
   buffer_free(&channels[channel].output);    buffer_free(&channels[channel].output);
Line 226 
Line 205 
           break;            break;
   
         case SSH_CHANNEL_OPEN:          case SSH_CHANNEL_OPEN:
           if (buffer_len(&ch->input) < 32768)            if(compat13){
             FD_SET(ch->sock, readset);              if (buffer_len(&ch->input) < 32768)
           if (buffer_len(&ch->output) > 0)                FD_SET(ch->sock, readset);
             FD_SET(ch->sock, writeset);              if (buffer_len(&ch->output) > 0)
           break;                FD_SET(ch->sock, writeset);
               break;
             }
             /* test whether sockets are 'alive' for read/write */
             if (!(ch->flags & CHAN_SHUT_RD))
               if (buffer_len(&ch->input) < 32768)
                 FD_SET(ch->sock, readset);
             if (!(ch->flags & CHAN_SHUT_WR)){
               if (buffer_len(&ch->output) > 0){
                 FD_SET(ch->sock, writeset);
               }else if(ch->flags & CHAN_IEOF_RCVD){
                 /* if output-buffer empty AND IEOF received,
                    we won't get more data for writing */
                 chan_shutdown_write(ch);
                 chan_send_oclose(ch);
               }
             }
             break;
   
         case SSH_CHANNEL_INPUT_DRAINING:          case SSH_CHANNEL_INPUT_DRAINING:
             if (!compat13)
               fatal("cannot happen: IN_DRAIN");
           if (buffer_len(&ch->input) == 0)            if (buffer_len(&ch->input) == 0)
             {              {
               packet_start(SSH_MSG_CHANNEL_CLOSE);                packet_start(SSH_MSG_CHANNEL_CLOSE);
Line 245 
Line 243 
           break;            break;
   
         case SSH_CHANNEL_OUTPUT_DRAINING:          case SSH_CHANNEL_OUTPUT_DRAINING:
             if (!compat13)
               fatal("cannot happen: OUT_DRAIN");
           if (buffer_len(&ch->output) == 0)            if (buffer_len(&ch->output) == 0)
             {              {
               /* debug("Freeing channel %d after output drain.", i); */                /* debug("Freeing channel %d after output drain.", i); */
Line 327 
Line 327 
           log("X11 connection rejected because of wrong authentication.\r\n");            log("X11 connection rejected because of wrong authentication.\r\n");
           buffer_clear(&ch->input);            buffer_clear(&ch->input);
           buffer_clear(&ch->output);            buffer_clear(&ch->output);
           close(ch->sock);            if (compat13) {
           ch->sock = -1;              close(ch->sock);
           ch->type = SSH_CHANNEL_CLOSED;              ch->sock = -1;
           packet_start(SSH_MSG_CHANNEL_CLOSE);              ch->type = SSH_CHANNEL_CLOSED;
           packet_put_int(ch->remote_id);              packet_start(SSH_MSG_CHANNEL_CLOSE);
           packet_send();              packet_put_int(ch->remote_id);
               packet_send();
             }else{
               chan_shutdown_read(ch);     /* shutdown, since close() does not update ch->flags */
               chan_send_ieof(ch);         /* no need to wait for output-buffer */
               chan_shutdown_write(ch);
               chan_send_oclose(ch);
             }
           break;            break;
   
         case SSH_CHANNEL_FREE:          case SSH_CHANNEL_FREE:
Line 441 
Line 448 
           /* This is an open two-way communication channel.  It is not of            /* This is an open two-way communication channel.  It is not of
              interest to us at this point what kind of data is being               interest to us at this point what kind of data is being
              transmitted. */               transmitted. */
           /* Read available incoming data and append it to buffer. */  
             /* Read available incoming data and append it to buffer;
                shutdown socket, if read or write failes */
           if (FD_ISSET(ch->sock, readset))            if (FD_ISSET(ch->sock, readset))
             {              {
               len = read(ch->sock, buf, sizeof(buf));                len = read(ch->sock, buf, sizeof(buf));
               if (len <= 0)                if (len <= 0)
                 {                  {
                   buffer_consume(&ch->output, buffer_len(&ch->output));                    if (compat13) {
                   ch->type = SSH_CHANNEL_INPUT_DRAINING;                      buffer_consume(&ch->output, buffer_len(&ch->output));
                   debug("Channel %d status set to input draining.", i);                      ch->type = SSH_CHANNEL_INPUT_DRAINING;
                       debug("Channel %d status set to input draining.", i);
                     }else{
                       buffer_consume(&ch->output, buffer_len(&ch->output));
                       chan_shutdown_read(ch);
                       /* we have to wait until the input-buffer has been
                          sent to our peer before we can send IEOF */
                     }
                   break;                    break;
                 }                  }
               buffer_append(&ch->input, buf, len);                buffer_append(&ch->input, buf, len);
Line 461 
Line 477 
                           buffer_len(&ch->output));                            buffer_len(&ch->output));
               if (len <= 0)                if (len <= 0)
                 {                  {
                   buffer_consume(&ch->output, buffer_len(&ch->output));                    if (compat13) {
                   debug("Channel %d status set to input draining.", i);                      buffer_consume(&ch->output, buffer_len(&ch->output));
                   ch->type = SSH_CHANNEL_INPUT_DRAINING;                      debug("Channel %d status set to input draining.", i);
                       ch->type = SSH_CHANNEL_INPUT_DRAINING;
                     }else{
                       buffer_consume(&ch->output, buffer_len(&ch->output));
                       chan_shutdown_write(ch);
                       chan_send_oclose(ch);
                     }
                   break;                    break;
                 }                  }
               buffer_consume(&ch->output, len);                buffer_consume(&ch->output, len);
             }              }
             chan_del_if_dead(ch);
           break;            break;
   
         case SSH_CHANNEL_OUTPUT_DRAINING:          case SSH_CHANNEL_OUTPUT_DRAINING:
             if (!compat13)
                   fatal("cannot happen: OUT_DRAIN");
           /* Send buffered output data to the socket. */            /* Send buffered output data to the socket. */
           if (FD_ISSET(ch->sock, writeset) && buffer_len(&ch->output) > 0)            if (FD_ISSET(ch->sock, writeset) && buffer_len(&ch->output) > 0)
             {              {
Line 528 
Line 553 
           packet_send();            packet_send();
           buffer_consume(&ch->input, len);            buffer_consume(&ch->input, len);
         }          }
         else if(ch->flags & CHAN_SHUT_RD)
           {
             if (compat13)
                fatal("cannot happen: CHAN_SHUT_RD set for proto 1.3");
             /* input-buffer is empty and read-socket shutdown:
                tell peer, that we will not send more data: send IEOF */
             chan_send_ieof(ch);
           }
     }      }
 }  }
   
Line 570 
Line 603 
   for (i = 0; i < channels_alloc; i++)    for (i = 0; i < channels_alloc; i++)
     {      {
       ch = &channels[i];        ch = &channels[i];
       switch (channels[i].type)        switch (ch->type)
         {          {
         case SSH_CHANNEL_X11_LISTENER:          case SSH_CHANNEL_X11_LISTENER:
         case SSH_CHANNEL_PORT_LISTENER:          case SSH_CHANNEL_PORT_LISTENER:
Line 593 
Line 626 
   return 1;    return 1;
 }  }
   
 /* This is called after receiving CHANNEL_CLOSE. */  /* This is called after receiving CHANNEL_CLOSE/IEOF. */
   
 void channel_input_close()  void channel_input_close()
 {  {
Line 605 
Line 638 
       channels[channel].type == SSH_CHANNEL_FREE)        channels[channel].type == SSH_CHANNEL_FREE)
     packet_disconnect("Received data for nonexistent channel %d.", channel);      packet_disconnect("Received data for nonexistent channel %d.", channel);
   
     if(!compat13){
       /* proto version 1.5 overloads CLOSE with IEOF */
       chan_rcvd_ieof(&channels[channel]);
       return;
     }
   
   /* Send a confirmation that we have closed the channel and no more data is    /* Send a confirmation that we have closed the channel and no more data is
      coming for it. */       coming for it. */
   packet_start(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION);    packet_start(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION);
Line 628 
Line 667 
     }      }
 }  }
   
 /* This is called after receiving CHANNEL_CLOSE_CONFIRMATION. */  /* This is called after receiving CHANNEL_CLOSE_CONFIRMATION/OCLOSE. */
   
 void channel_input_close_confirmation()  void channel_input_close_confirmation()
 {  {
Line 639 
Line 678 
   if (channel < 0 || channel >= channels_alloc)    if (channel < 0 || channel >= channels_alloc)
     packet_disconnect("Received close confirmation for out-of-range channel %d.",      packet_disconnect("Received close confirmation for out-of-range channel %d.",
                       channel);                        channel);
   
     if(!compat13){
       /* proto version 1.5 overloads CLOSE_CONFIRMATION with OCLOSE */
       chan_rcvd_oclose(&channels[channel]);
       return;
     }
   
   if (channels[channel].type != SSH_CHANNEL_CLOSED)    if (channels[channel].type != SSH_CHANNEL_CLOSED)
     packet_disconnect("Received close confirmation for non-closed channel %d (type %d).",      packet_disconnect("Received close confirmation for non-closed channel %d (type %d).",
                       channel, channels[channel].type);                        channel, channels[channel].type);
Line 748 
Line 794 
       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:
           return 1;
       case SSH_CHANNEL_INPUT_DRAINING:        case SSH_CHANNEL_INPUT_DRAINING:
       case SSH_CHANNEL_OUTPUT_DRAINING:        case SSH_CHANNEL_OUTPUT_DRAINING:
           if (!compat13)
             fatal("cannot happen: OUT_DRAIN");
         return 1;          return 1;
       default:        default:
         fatal("channel_still_open: bad channel type %d", channels[i].type);          fatal("channel_still_open: bad channel type %d", channels[i].type);
Line 771 
Line 820 
   buffer_init(&buffer);    buffer_init(&buffer);
   sprintf(buf, "The following connections are open:\r\n");    sprintf(buf, "The following connections are open:\r\n");
   buffer_append(&buffer, buf, strlen(buf));    buffer_append(&buffer, buf, strlen(buf));
   for (i = 0; i < channels_alloc; i++)    for (i = 0; i < channels_alloc; i++){
     switch (channels[i].type)      Channel *c=&channels[i];
       switch (c->type)
       {        {
       case SSH_CHANNEL_FREE:        case SSH_CHANNEL_FREE:
       case SSH_CHANNEL_X11_LISTENER:        case SSH_CHANNEL_X11_LISTENER:
Line 785 
Line 835 
       case SSH_CHANNEL_X11_OPEN:        case SSH_CHANNEL_X11_OPEN:
       case SSH_CHANNEL_INPUT_DRAINING:        case SSH_CHANNEL_INPUT_DRAINING:
       case SSH_CHANNEL_OUTPUT_DRAINING:        case SSH_CHANNEL_OUTPUT_DRAINING:
         sprintf(buf, "  %.300s\r\n", channels[i].remote_name);          snprintf(buf, sizeof buf, "  #%d/%d %.300s\r\n",
                    c->self,c->type,c->remote_name);
         buffer_append(&buffer, buf, strlen(buf));          buffer_append(&buffer, buf, strlen(buf));
         continue;          continue;
       default:        default:
         fatal("channel_still_open: bad channel type %d", channels[i].type);          fatal("channel_still_open: bad channel type %d", c->type);
         /*NOTREACHED*/          /*NOTREACHED*/
       }        }
     }
   buffer_append(&buffer, "\0", 1);    buffer_append(&buffer, "\0", 1);
   cp = xstrdup(buffer_ptr(&buffer));    cp = xstrdup(buffer_ptr(&buffer));
   buffer_free(&buffer);    buffer_free(&buffer);

Legend:
Removed from v.1.13  
changed lines
  Added in v.1.14