*** sshconnect.c.orig	Wed May 12 20:19:29 1999
--- sshconnect.c	Thu Feb 24 22:34:47 2000
***************
*** 337,343 ****
  
  /* Creates a (possibly privileged) socket for use as the ssh connection. */
  
! int ssh_create_socket(uid_t original_real_uid, int privileged)
  {
    int sock;
  
--- 337,343 ----
  
  /* Creates a (possibly privileged) socket for use as the ssh connection. */
  
! int ssh_create_socket(uid_t original_real_uid, int privileged, int family)
  {
    int sock;
  
***************
*** 345,379 ****
       bind our own socket to a privileged port. */
    if (privileged)
      {
!       struct sockaddr_in sin;
        int p;
        for (p = 1023; p > 512; p--)
          {
!           sock = socket(AF_INET, SOCK_STREAM, 0);
            if (sock < 0)
!             fatal("socket: %.100s", strerror(errno));
            
!           /* Initialize the desired sockaddr_in structure. */
!           memset(&sin, 0, sizeof(sin));
!           sin.sin_family = AF_INET;
!           sin.sin_addr.s_addr = INADDR_ANY;
!           sin.sin_port = htons(p);
  
            /* Try to bind the socket to the privileged port. */
  #if defined(SOCKS)
!           if (Rbind(sock, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
              break; /* Success. */
  #else /* SOCKS */
!           if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
              break; /* Success. */
  #endif /* SOCKS */
            if (errno == EADDRINUSE)
              {
                close(sock);
                continue;
              }
!           fatal("bind: %.100s", strerror(errno));
          }
        debug("Allocated local port %d.", p);
      }
    else
--- 345,404 ----
       bind our own socket to a privileged port. */
    if (privileged)
      {
!       struct addrinfo hints, *ai = NULL;
!       int errgai;
!       char strport[PORTSTRLEN];
        int p;
+ #if (defined(__OpenBSD__) || defined(__FreeBSD__))  && !defined(SOCKS)
+       p = 1023;	/* Compat with old FreeBSD */
+ #if __FreeBSD__ >= 400014
+       sock = rresvport_af(&p, family);
+         if (sock < 0)
+           error("rresvport_af: %.100s", strerror(errno));
+ #else
+       sock = rresvport(&p);
+         if (sock < 0)
+           error("rresvport: %.100s", strerror(errno));
+ #endif
+ #else
        for (p = 1023; p > 512; p--)
          {
! 	  sock = socket(family, SOCK_STREAM, 0);
            if (sock < 0)
!             error("socket: %.100s", strerror(errno));
            
! 	  /* Initialize the desired addrinfo structure. */
! 	  memset(&hints, 0, sizeof(hints));
! 	  hints.ai_family = family;
! 	  hints.ai_flags = AI_PASSIVE;
! 	  hints.ai_socktype = SOCK_STREAM;
! 	  sprintf(strport, "%d", p);
! #if defined(SOCKS)
! 	  if ((errgai = Rgetaddrinfo(NULL, strport, &hints, &ai)) != 0)
! 	    fatal("getaddrinfo: %.100s", gai_strerror(errgai));
! #else /* SOCKS */
! 	  if ((errgai = getaddrinfo(NULL, strport, &hints, &ai)) != 0)
! 	    fatal("getaddrinfo: %.100s", gai_strerror(errgai));
! #endif /* SOCKS */
  
            /* Try to bind the socket to the privileged port. */
  #if defined(SOCKS)
! 	  if (Rbind(sock, ai->ai_addr, ai->ai_addrlen) >= 0)
              break; /* Success. */
  #else /* SOCKS */
! 	  if (bind(sock, ai->ai_addr, ai->ai_addrlen) >= 0)
              break; /* Success. */
  #endif /* SOCKS */
            if (errno == EADDRINUSE)
              {
                close(sock);
+ 	      freeaddrinfo(ai);
                continue;
              }
!           error("bind: %.100s", strerror(errno));
          }
+       freeaddrinfo(ai);
+ #endif
        debug("Allocated local port %d.", p);
      }
    else
***************
*** 396,409 ****
     the daemon. */
  
  int ssh_connect(const char *host, int port, int connection_attempts,
                  int anonymous, uid_t original_real_uid, 
                  const char *proxy_command, RandomState *random_state)
  {
    int sock = -1, attempt, i;
    int on = 1;
    struct servent *sp;
!   struct hostent *hp;
!   struct sockaddr_in hostaddr;
  #if defined(SO_LINGER) && defined(ENABLE_SO_LINGER)
    struct linger linger;
  #endif /* SO_LINGER */
--- 421,439 ----
     the daemon. */
  
  int ssh_connect(const char *host, int port, int connection_attempts,
+ #ifdef ENABLE_ANOTHER_PORT_TRY
+ 		int another_port,
+ #endif /* ENABLE_ANOTHER_PORT_TRY */
                  int anonymous, uid_t original_real_uid, 
                  const char *proxy_command, RandomState *random_state)
  {
    int sock = -1, attempt, i;
    int on = 1;
    struct servent *sp;
!   struct addrinfo hints, *ai, *aitop, *aitmp;
!   struct sockaddr_storage hostaddr;
!   char ntop[ADDRSTRLEN], strport[PORTSTRLEN];
!   int gaierr;
  #if defined(SO_LINGER) && defined(ENABLE_SO_LINGER)
    struct linger linger;
  #endif /* SO_LINGER */
***************
*** 421,430 ****
          port = SSH_DEFAULT_PORT;
      }
  
-   /* Map localhost to ip-address locally */
-   if (strcmp(host, "localhost") == 0)
-     host = "127.0.0.1";
-   
    /* If a proxy command is given, connect using it. */
    if (proxy_command != NULL && *proxy_command)
      return ssh_proxy_connect(host, port, original_real_uid, proxy_command,
--- 451,456 ----
***************
*** 432,440 ****
  
    /* No proxy command. */
  
!   /* No host lookup made yet. */
!   hp = NULL;
!   
    /* Try to connect several times.  On some machines, the first time will
       sometimes fail.  In general socket code appears to behave quite
       magically on many machines. */
--- 458,495 ----
  
    /* No proxy command. */
  
!   memset(&hints, 0, sizeof(hints));
!   hints.ai_family = IPv4or6;
!   hints.ai_socktype = SOCK_STREAM;
!   sprintf(strport, "%d", port);
! #if defined(SOCKS)
!   if ((gaierr = Rgetaddrinfo(host, strport, &hints, &aitop)) != 0)
!     fatal("Bad host name: %.100s (%s)", host, gai_strerror(gaierr));
! #else /* SOCKS */
!   if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0)
!     fatal("Bad host name: %.100s (%s)", host, gai_strerror(gaierr));
! #endif /* SOCKS */
! 
! #ifdef ENABLE_ANOTHER_PORT_TRY
!   if (another_port)
!     {
!       aitmp = aitop;
!       memset(&hints, 0, sizeof(hints));
!       hints.ai_family = IPv4or6;
!       hints.ai_socktype = SOCK_STREAM;
!       sprintf(strport, "%d", another_port);
! #if defined(SOCKS)
!       if ((gaierr = Rgetaddrinfo(host, strport, &hints, &aitop)) != 0)
! 	fatal("Bad host name: %.100s (%s)", host, gai_strerror(gaierr));
! #else /* SOCKS */
!       if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0)
! 	fatal("Bad host name: %.100s (%s)", host, gai_strerror(gaierr));
! #endif /* SOCKS */
!       for (ai = aitop; ai->ai_next; ai = ai->ai_next);
!       ai->ai_next = aitmp;
!     }
! #endif /* ENABLE_ANOTHER_PORT_TRY */
! 
    /* Try to connect several times.  On some machines, the first time will
       sometimes fail.  In general socket code appears to behave quite
       magically on many machines. */
***************
*** 443,545 ****
        if (attempt > 0)
          debug("Trying again...");
  
-       /* Try to parse the host name as a numeric inet address. */
-       memset(&hostaddr, 0, sizeof(hostaddr));
-       hostaddr.sin_family = AF_INET;
-       hostaddr.sin_port = htons(port);
- #ifdef BROKEN_INET_ADDR
-       hostaddr.sin_addr.s_addr = inet_network(host);
- #else /* BROKEN_INET_ADDR */
-       hostaddr.sin_addr.s_addr = inet_addr(host);
- #endif /* BROKEN_INET_ADDR */
-       if ((hostaddr.sin_addr.s_addr & 0xffffffff) != 0xffffffff)
-         { 
-           /* Create a socket. */
-           sock = ssh_create_socket(original_real_uid, 
-                                    !anonymous && geteuid() == UID_ROOT);
-       
-           /* Valid numeric IP address */
-           debug("Connecting to %.100s port %d.", 
-                 inet_ntoa(hostaddr.sin_addr), port);
- 
-           /* Connect to the host. */
- #if defined(SOCKS)
-           if (Rconnect(sock, (struct sockaddr *)&hostaddr, sizeof(hostaddr))
- #else /* SOCKS */
-           if (connect(sock, (struct sockaddr *)&hostaddr, sizeof(hostaddr))
- #endif /* SOCKS */
-               >= 0)
-             {
-               /* Successful connect. */
-               break;
-             }
-           debug("connect: %.100s", strerror(errno));
- 
-           /* Destroy the failed socket. */
-           shutdown(sock, 2);
-           close(sock);
-         }
-       else
-         { 
-           /* Not a valid numeric inet address. */
-           /* Map host name to an address. */
-           if (!hp)
-             {
-               struct hostent *hp_static;
- 
- #if defined(SOCKS5)
-               hp_static = Rgethostbyname(host);
- #else
-               hp_static = gethostbyname(host);
- #endif
-               if (hp_static)
-                 {
-                   hp = xmalloc(sizeof(struct hostent));
-                   memcpy(hp, hp_static, sizeof(struct hostent));
- 
-                   /* Copy list of addresses, not just pointers.
-                      We don't use h_name & h_aliases so leave them as is */
-                   for (i = 0; hp_static->h_addr_list[i]; i++)
-                     ; /* count them */
-                   hp->h_addr_list = xmalloc((i + 1) *
-                                             sizeof(hp_static->h_addr_list[0]));
-                   for (i = 0; hp_static->h_addr_list[i]; i++)
-                     {
-                       hp->h_addr_list[i] = xmalloc(hp->h_length);
-                       memcpy(hp->h_addr_list[i], hp_static->h_addr_list[i],
-                              hp->h_length);
-                     }
-                   hp->h_addr_list[i] = NULL; /* last one */
-                 }
-             }
-           if (!hp)
-             fatal("Bad host name: %.100s", host);
-           if (!hp->h_addr_list[0])
-             fatal("Host does not have an IP address: %.100s", host);
- 
            /* Loop through addresses for this host, and try each one in
               sequence until the connection succeeds. */
!           for (i = 0; hp->h_addr_list[i]; i++)
              {
!               /* Set the address to connect to. */
!               hostaddr.sin_family = hp->h_addrtype;
!               memcpy(&hostaddr.sin_addr, hp->h_addr_list[i],
!                      sizeof(hostaddr.sin_addr));
  
!               debug("Connecting to %.200s [%.100s] port %d.",
!                     host, inet_ntoa(hostaddr.sin_addr), port);
  
                /* Create a socket for connecting. */
                sock = ssh_create_socket(original_real_uid, 
!                                        !anonymous && geteuid() == UID_ROOT);
  
                /* Connect to the host. */
  #if defined(SOCKS)
!               if (Rconnect(sock, (struct sockaddr *)&hostaddr, 
!                            sizeof(hostaddr)) >= 0)
  #else /* SOCKS */
!               if (connect(sock, (struct sockaddr *)&hostaddr, 
!                           sizeof(hostaddr)) >= 0)
  #endif /* SOCKS */
                  {
                    /* Successful connection. */
--- 498,526 ----
        if (attempt > 0)
          debug("Trying again...");
  
            /* Loop through addresses for this host, and try each one in
               sequence until the connection succeeds. */
!           for (ai = aitop; ai; ai = ai->ai_next)
              {
! 	      getnameinfo(ai->ai_addr, ai->ai_addrlen,
! 			  ntop, sizeof(ntop), strport, sizeof(strport),
! 			  NI_NUMERICHOST|NI_NUMERICSERV);
  
! 	      debug("Connecting to %.200s [%.100s] port %s.",
! 		    host, ntop, strport);
  
                /* Create a socket for connecting. */
                sock = ssh_create_socket(original_real_uid, 
! 				       !anonymous && geteuid() == UID_ROOT,
! 				       ai->ai_family);
! 	      if (sock < 0)
! 		      continue;
  
                /* Connect to the host. */
  #if defined(SOCKS)
! 	      if (Rconnect(sock, ai->ai_addr, ai->ai_addrlen) >= 0)
  #else /* SOCKS */
! 	      if (connect(sock, ai->ai_addr, ai->ai_addrlen) >= 0)
  #endif /* SOCKS */
                  {
                    /* Successful connection. */
***************
*** 552,573 ****
                   returned an error. */
                shutdown(sock, 2);
                close(sock);
!             }
!           if (hp->h_addr_list[i])
              break; /* Successful connection. */
-         }
  
        /* Sleep a moment before retrying. */
        sleep(1);
      }
  
!   if (hp)
!     {
!       for (i = 0; hp->h_addr_list[i]; i++)
!         xfree(hp->h_addr_list[i]);
!       xfree(hp->h_addr_list);
!       xfree(hp);
!     }
  
    /* Return failure if we didn't get a successful connection. */
    if (attempt >= connection_attempts)
--- 533,547 ----
                   returned an error. */
                shutdown(sock, 2);
                close(sock);
! 	    } /* for (ai = aitop; ai; ai = ai->ai_next) */
!           if (ai)
              break; /* Successful connection. */
  
        /* Sleep a moment before retrying. */
        sleep(1);
      }
  
!   freeaddrinfo(aitop);
  
    /* Return failure if we didn't get a successful connection. */
    if (attempt >= connection_attempts)
***************
*** 946,952 ****
    int ap_opts, ret_stat = 0;
    krb5_keyblock   *session_key = 0;
    krb5_ap_rep_enc_part *repl = 0;
!   struct sockaddr_in local, foreign;
    
    memset(&auth, 0 , sizeof(auth));
    remotehost = (char *) get_canonical_hostname();
--- 920,926 ----
    int ap_opts, ret_stat = 0;
    krb5_keyblock   *session_key = 0;
    krb5_ap_rep_enc_part *repl = 0;
!   struct sockaddr_storage local, foreign;
    
    memset(&auth, 0 , sizeof(auth));
    remotehost = (char *) get_canonical_hostname();
