[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.34 and 1.35

version 1.34, 1999/12/27 09:48:38 version 1.35, 2000/01/04 00:07:58
Line 374 
Line 374 
 channel_after_select(fd_set * readset, fd_set * writeset)  channel_after_select(fd_set * readset, fd_set * writeset)
 {  {
         struct sockaddr addr;          struct sockaddr addr;
         int addrlen, newsock, i, newch, len;          int newsock, i, newch, len;
           socklen_t addrlen;
         Channel *ch;          Channel *ch;
         char buf[16384], *remote_hostname;          char buf[16384], *remote_hostname;
   
Line 412 
Line 413 
                          * forwarded TCP/IP port.                           * forwarded TCP/IP port.
                          */                           */
                         if (FD_ISSET(ch->sock, readset)) {                          if (FD_ISSET(ch->sock, readset)) {
                                 debug("Connection to port %d forwarding to %.100s:%d requested.",                                  debug("Connection to port %d forwarding to %.100s port %d requested.",
                                       ch->listening_port, ch->path, ch->host_port);                                        ch->listening_port, ch->path, ch->host_port);
                                 addrlen = sizeof(addr);                                  addrlen = sizeof(addr);
                                 newsock = accept(ch->sock, &addr, &addrlen);                                  newsock = accept(ch->sock, &addr, &addrlen);
Line 421 
Line 422 
                                         break;                                          break;
                                 }                                  }
                                 remote_hostname = get_remote_hostname(newsock);                                  remote_hostname = get_remote_hostname(newsock);
                                 snprintf(buf, sizeof buf, "listen port %d:%.100s:%d, connect from %.200s:%d",                                  snprintf(buf, sizeof buf, "listen port %d for %.100s port %d, connect from %.200s port %d",
                                          ch->listening_port, ch->path, ch->host_port,                                           ch->listening_port, ch->path, ch->host_port,
                                 remote_hostname, get_peer_port(newsock));                                  remote_hostname, get_peer_port(newsock));
                                 xfree(remote_hostname);                                  xfree(remote_hostname);
Line 878 
Line 879 
 channel_request_local_forwarding(u_short port, const char *host,  channel_request_local_forwarding(u_short port, const char *host,
                                  u_short host_port, int gateway_ports)                                   u_short host_port, int gateway_ports)
 {  {
         int ch, sock, on = 1;          int success, ch, sock, on = 1;
         struct sockaddr_in sin;          struct addrinfo hints, *ai, *aitop;
           char ntop[NI_MAXHOST], strport[NI_MAXSERV];
         struct linger linger;          struct linger linger;
   
         if (strlen(host) > sizeof(channels[0].path) - 1)          if (strlen(host) > sizeof(channels[0].path) - 1)
                 packet_disconnect("Forward host name too long.");                  packet_disconnect("Forward host name too long.");
   
         /* Create a port to listen for the host. */  
         sock = socket(AF_INET, SOCK_STREAM, 0);  
         if (sock < 0)  
                 packet_disconnect("socket: %.100s", strerror(errno));  
   
         /* Initialize socket address. */  
         memset(&sin, 0, sizeof(sin));  
         sin.sin_family = AF_INET;  
         if (gateway_ports == 1)  
                 sin.sin_addr.s_addr = htonl(INADDR_ANY);  
         else  
                 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);  
         sin.sin_port = htons(port);  
   
         /*          /*
          * Set socket options.  We would like the socket to disappear as soon           * getaddrinfo returns a loopback address if the hostname is
          * as it has been closed for whatever reason.           * set to NULL and hints.ai_flags is not AI_PASSIVE
          */           */
         setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on));          memset(&hints, 0, sizeof(hints));
         linger.l_onoff = 1;          hints.ai_family = IPv4or6;
         linger.l_linger = 5;          hints.ai_flags = gateway_ports ? AI_PASSIVE : 0;
         setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *) &linger, sizeof(linger));          hints.ai_socktype = SOCK_STREAM;
           snprintf(strport, sizeof strport, "%d", port);
           if (getaddrinfo(NULL, strport, &hints, &aitop) != 0)
                   packet_disconnect("getaddrinfo: fatal error");
   
         /* Bind the socket to the address. */          success = 0;
         if (bind(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0)          for (ai = aitop; ai; ai = ai->ai_next) {
                 packet_disconnect("bind: %.100s", strerror(errno));                  if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
                           continue;
                   if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),
                       strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
                           error("channel_request_local_forwarding: getnameinfo failed");
                           continue;
                   }
                   /* Create a port to listen for the host. */
                   sock = socket(ai->ai_family, SOCK_STREAM, 0);
                   if (sock < 0) {
                           /* this is no error since kernel may not support ipv6 */
                           verbose("socket: %.100s", strerror(errno));
                           continue;
                   }
                   /*
                    * Set socket options.  We would like the socket to disappear
                    * as soon as it has been closed for whatever reason.
                    */
                   setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on));
                   linger.l_onoff = 1;
                   linger.l_linger = 5;
                   setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *)&linger, sizeof(linger));
                   debug("Local forwarding listening on %s port %s.", ntop, strport);
   
         /* Start listening for connections on the socket. */                  /* Bind the socket to the address. */
         if (listen(sock, 5) < 0)                  if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
                 packet_disconnect("listen: %.100s", strerror(errno));                          /* address can be in use ipv6 address is already bound */
                           verbose("bind: %.100s", strerror(errno));
         /* Allocate a channel number for the socket. */                          close(sock);
         ch = channel_allocate(SSH_CHANNEL_PORT_LISTENER, sock,                          continue;
                               xstrdup("port listener"));                  }
         strlcpy(channels[ch].path, host, sizeof(channels[ch].path));                  /* Start listening for connections on the socket. */
         channels[ch].host_port = host_port;                  if (listen(sock, 5) < 0) {
         channels[ch].listening_port = port;                          error("listen: %.100s", strerror(errno));
                           close(sock);
                           continue;
                   }
                   /* Allocate a channel number for the socket. */
                   ch = channel_allocate(SSH_CHANNEL_PORT_LISTENER, sock,
                       xstrdup("port listener"));
                   strlcpy(channels[ch].path, host, sizeof(channels[ch].path));
                   channels[ch].host_port = host_port;
                   channels[ch].listening_port = port;
                   success = 1;
           }
           if (success == 0)
                   packet_disconnect("cannot listen port: %d", port);
           freeaddrinfo(aitop);
 }  }
   
 /*  /*
Line 1000 
Line 1027 
 void  void
 channel_input_port_open(int payload_len)  channel_input_port_open(int payload_len)
 {  {
         int remote_channel, sock, newch, i;          int remote_channel, sock = 0, newch, i;
         u_short host_port;          u_short host_port;
         struct sockaddr_in sin;  
         char *host, *originator_string;          char *host, *originator_string;
         struct hostent *hp;  
         int host_len, originator_len;          int host_len, originator_len;
           struct addrinfo hints, *ai, *aitop;
           char ntop[NI_MAXHOST], strport[NI_MAXSERV];
           int gaierr;
   
         /* Get remote channel number. */          /* Get remote channel number. */
         remote_channel = packet_get_int();          remote_channel = packet_get_int();
Line 1047 
Line 1075 
                         packet_send();                          packet_send();
                 }                  }
         }          }
         memset(&sin, 0, sizeof(sin));  
         sin.sin_addr.s_addr = inet_addr(host);          memset(&hints, 0, sizeof(hints));
         if ((sin.sin_addr.s_addr & 0xffffffff) != 0xffffffff) {          hints.ai_family = IPv4or6;
                 /* It was a valid numeric host address. */          hints.ai_socktype = SOCK_STREAM;
                 sin.sin_family = AF_INET;          snprintf(strport, sizeof strport, "%d", host_port);
         } else {          if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) {
                 /* Look up the host address from the name servers. */                  error("%.100s: unknown host (%s)", host, gai_strerror(gaierr));
                 hp = gethostbyname(host);                  goto fail;
                 if (!hp) {          }
                         error("%.100s: unknown host.", host);  
                         goto fail;          for (ai = aitop; ai; ai = ai->ai_next) {
                   if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
                           continue;
                   if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),
                       strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
                           error("channel_input_port_open: getnameinfo failed");
                           continue;
                 }                  }
                 if (!hp->h_addr_list[0]) {                  /* Create the socket. */
                         error("%.100s: host has no IP address.", host);                  sock = socket(ai->ai_family, SOCK_STREAM, 0);
                         goto fail;                  if (sock < 0) {
                           error("socket: %.100s", strerror(errno));
                           continue;
                 }                  }
                 sin.sin_family = hp->h_addrtype;                  /* Connect to the host/port. */
                 memcpy(&sin.sin_addr, hp->h_addr_list[0],                  if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
                        sizeof(sin.sin_addr));                          error("connect %.100s port %s: %.100s", ntop, strport,
                               strerror(errno));
                           close(sock);
                           continue;       /* fail -- try next */
                   }
                   break; /* success */
   
         }          }
         sin.sin_port = htons(host_port);          freeaddrinfo(aitop);
   
         /* Create the socket. */          if (!ai) {
         sock = socket(sin.sin_family, SOCK_STREAM, 0);                  error("connect %.100s port %d: failed.", host, host_port);
         if (sock < 0) {  
                 error("socket: %.100s", strerror(errno));  
                 goto fail;                  goto fail;
         }          }
         /* Connect to the host/port. */  
         if (connect(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0) {  
                 error("connect %.100s:%d: %.100s", host, host_port,  
                       strerror(errno));  
                 close(sock);  
                 goto fail;  
         }  
         /* Successful connection. */          /* Successful connection. */
   
         /* Allocate a channel for this connection. */          /* Allocate a channel for this connection. */
Line 1115 
Line 1149 
  * occurs.   * occurs.
  */   */
   
   #define NUM_SOCKS       10
   
 char *  char *
 x11_create_display_inet(int screen_number, int x11_display_offset)  x11_create_display_inet(int screen_number, int x11_display_offset)
 {  {
         int display_number, sock;          int display_number, sock;
         u_short port;          u_short port;
         struct sockaddr_in sin;          struct addrinfo hints, *ai, *aitop;
         char buf[512];          char strport[NI_MAXSERV];
           int gaierr, n, num_socks = 0, socks[NUM_SOCKS];
           char display[512];
         char hostname[MAXHOSTNAMELEN];          char hostname[MAXHOSTNAMELEN];
   
         for (display_number = x11_display_offset;          for (display_number = x11_display_offset;
              display_number < MAX_DISPLAYS;               display_number < MAX_DISPLAYS;
              display_number++) {               display_number++) {
                 port = 6000 + display_number;                  port = 6000 + display_number;
                 memset(&sin, 0, sizeof(sin));                  memset(&hints, 0, sizeof(hints));
                 sin.sin_family = AF_INET;                  hints.ai_family = IPv4or6;
                 sin.sin_addr.s_addr = htonl(INADDR_ANY);                  hints.ai_flags = 0 /*AI_PASSIVE*/;      /* XXX loopback only ? */
                 sin.sin_port = htons(port);                  hints.ai_socktype = SOCK_STREAM;
                   snprintf(strport, sizeof strport, "%d", port);
                 sock = socket(AF_INET, SOCK_STREAM, 0);                  if ((gaierr = getaddrinfo(NULL, strport, &hints, &aitop)) != 0) {
                 if (sock < 0) {                          error("getaddrinfo: %.100s", gai_strerror(gaierr));
                         error("socket: %.100s", strerror(errno));  
                         return NULL;                          return NULL;
                 }                  }
                 if (bind(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0) {                  for (ai = aitop; ai; ai = ai->ai_next) {
                         debug("bind port %d: %.100s", port, strerror(errno));                          if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
                         shutdown(sock, SHUT_RDWR);                                  continue;
                         close(sock);                          sock = socket(ai->ai_family, SOCK_STREAM, 0);
                         continue;                          if (sock < 0) {
                                   error("socket: %.100s", strerror(errno));
                                   return NULL;
                           }
                           if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
                                   debug("bind port %d: %.100s", port, strerror(errno));
                                   shutdown(sock, SHUT_RDWR);
                                   close(sock);
                                   for (n = 0; n < num_socks; n++) {
                                           shutdown(socks[n], SHUT_RDWR);
                                           close(socks[n]);
                                   }
                                   num_socks = 0;
                                   break;
                           }
                           socks[num_socks++] = sock;
                           if (num_socks == NUM_SOCKS)
                                   break;
                 }                  }
                 break;                  if (num_socks > 0)
                           break;
         }          }
         if (display_number >= MAX_DISPLAYS) {          if (display_number >= MAX_DISPLAYS) {
                 error("Failed to allocate internet-domain X11 display socket.");                  error("Failed to allocate internet-domain X11 display socket.");
                 return NULL;                  return NULL;
         }          }
         /* Start listening for connections on the socket. */          /* Start listening for connections on the socket. */
         if (listen(sock, 5) < 0) {          for (n = 0; n < num_socks; n++) {
                 error("listen: %.100s", strerror(errno));                  sock = socks[n];
                 shutdown(sock, SHUT_RDWR);                  if (listen(sock, 5) < 0) {
                 close(sock);                          error("listen: %.100s", strerror(errno));
                 return NULL;                          shutdown(sock, SHUT_RDWR);
                           close(sock);
                           return NULL;
                   }
         }          }
   
         /* Set up a suitable value for the DISPLAY variable. */          /* Set up a suitable value for the DISPLAY variable. */
         if (gethostname(hostname, sizeof(hostname)) < 0)          if (gethostname(hostname, sizeof(hostname)) < 0)
                 fatal("gethostname: %.100s", strerror(errno));                  fatal("gethostname: %.100s", strerror(errno));
         snprintf(buf, sizeof buf, "%.400s:%d.%d", hostname,          snprintf(display, sizeof display, "%.400s:%d.%d", hostname,
                  display_number, screen_number);                   display_number, screen_number);
   
         /* Allocate a channel for the socket. */          /* Allocate a channel for each socket. */
         (void) channel_allocate(SSH_CHANNEL_X11_LISTENER, sock,          for (n = 0; n < num_socks; n++) {
                                 xstrdup("X11 inet listener"));                  sock = socks[n];
                   (void) channel_allocate(SSH_CHANNEL_X11_LISTENER, sock,
                                           xstrdup("X11 inet listener"));
           }
   
         /* Return a suitable value for the DISPLAY environment variable. */          /* Return a suitable value for the DISPLAY environment variable. */
         return xstrdup(buf);          return xstrdup(display);
 }  }
   
 #ifndef X_UNIX_PATH  #ifndef X_UNIX_PATH
Line 1214 
Line 1276 
 void  void
 x11_input_open(int payload_len)  x11_input_open(int payload_len)
 {  {
         int remote_channel, display_number, sock, newch;          int remote_channel, display_number, sock = 0, newch;
         const char *display;          const char *display;
         struct sockaddr_in sin;  
         char buf[1024], *cp, *remote_host;          char buf[1024], *cp, *remote_host;
         struct hostent *hp;  
         int remote_len;          int remote_len;
           struct addrinfo hints, *ai, *aitop;
           char strport[NI_MAXSERV];
           int gaierr;
   
         /* Get remote channel number. */          /* Get remote channel number. */
         remote_channel = packet_get_int();          remote_channel = packet_get_int();
Line 1285 
Line 1348 
                       display);                        display);
                 goto fail;                  goto fail;
         }          }
         /* Try to parse the host name as a numeric IP address. */  
         memset(&sin, 0, sizeof(sin));  
         sin.sin_addr.s_addr = inet_addr(buf);  
         if ((sin.sin_addr.s_addr & 0xffffffff) != 0xffffffff) {  
                 /* It was a valid numeric host address. */  
                 sin.sin_family = AF_INET;  
         } else {  
                 /* Not a numeric IP address. */  
                 /* Look up the host address from the name servers. */  
                 hp = gethostbyname(buf);  
                 if (!hp) {  
                         error("%.100s: unknown host.", buf);  
                         goto fail;  
                 }  
                 if (!hp->h_addr_list[0]) {  
                         error("%.100s: host has no IP address.", buf);  
                         goto fail;  
                 }  
                 sin.sin_family = hp->h_addrtype;  
                 memcpy(&sin.sin_addr, hp->h_addr_list[0],  
                        sizeof(sin.sin_addr));  
         }  
         /* Set port number. */  
         sin.sin_port = htons(6000 + display_number);  
   
         /* Create a socket. */          /* Look up the host address */
         sock = socket(sin.sin_family, SOCK_STREAM, 0);          memset(&hints, 0, sizeof(hints));
         if (sock < 0) {          hints.ai_family = IPv4or6;
                 error("socket: %.100s", strerror(errno));          hints.ai_socktype = SOCK_STREAM;
           snprintf(strport, sizeof strport, "%d", 6000 + display_number);
           if ((gaierr = getaddrinfo(buf, strport, &hints, &aitop)) != 0) {
                   error("%.100s: unknown host. (%s)", buf, gai_strerror(gaierr));
                 goto fail;                  goto fail;
         }          }
           for (ai = aitop; ai; ai = ai->ai_next) {
                   /* Create a socket. */
                   sock = socket(ai->ai_family, SOCK_STREAM, 0);
                   if (sock < 0) {
                           debug("socket: %.100s", strerror(errno));
                   continue;
           }
         /* Connect it to the display. */          /* Connect it to the display. */
         if (connect(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0) {          if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
                 error("connect %.100s:%d: %.100s", buf, 6000 + display_number,                  debug("connect %.100s port %d: %.100s", buf, 6000 + display_number,
                       strerror(errno));                      strerror(errno));
                 close(sock);                  close(sock);
                   continue;
           }
           /* Success */
           break;
   
           } /* (ai = aitop, ai; ai = ai->ai_next) */
           freeaddrinfo(aitop);
           if (!ai) {
                   error("connect %.100s port %d: %.100s", buf, 6000 + display_number,
                       strerror(errno));
                 goto fail;                  goto fail;
         }          }
 success:  success:

Legend:
Removed from v.1.34  
changed lines
  Added in v.1.35