*** sshconnect.c.orig Wed May 12 13:19:29 1999 --- sshconnect.c Wed Jan 12 00:34:55 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,385 **** 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 { /* Just create an ordinary socket on arbitrary port. */ ! sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) fatal("socket: %.100s", strerror(errno)); } --- 345,392 ---- bind our own socket to a privileged port. */ if (privileged) { ! struct addrinfo hints, *ai = NULL; ! int errgai; ! char strport[PORTSTRLEN]; int p; for (p = 1023; p > 512; p--) { ! sock = socket(family, SOCK_STREAM, 0); if (sock < 0) fatal("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 ((errgai = getaddrinfo(NULL, strport, &hints, &ai)) != 0) ! fatal("getaddrinfo: %.100s", gai_strerror(errgai)); /* 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; } fatal("bind: %.100s", strerror(errno)); } debug("Allocated local port %d.", p); + freeaddrinfo(ai); } else { /* Just create an ordinary socket on arbitrary port. */ ! sock = socket(family, SOCK_STREAM, 0); if (sock < 0) fatal("socket: %.100s", strerror(errno)); } *************** *** 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 */ --- 403,421 ---- 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, --- 433,438 ---- *************** *** 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. */ --- 440,467 ---- /* No proxy command. */ ! memset(&hints, 0, sizeof(hints)); ! hints.ai_family = IPv4or6; ! hints.ai_socktype = SOCK_STREAM; ! sprintf(strport, "%d", port); ! if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) ! fatal("Bad host name: %.100s (%s)", host, gai_strerror(gaierr)); ! ! #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 ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) ! fatal("Bad host name: %.100s (%s)", host, gai_strerror(gaierr)); ! 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. */ --- 470,496 ---- 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); /* 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) --- 503,517 ---- 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) *************** *** 578,586 **** --- 522,532 ---- /* 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)); */ + #if 0 /* XXX */ #if defined(TCP_NODELAY) && defined(ENABLE_TCP_NODELAY) setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void *)&on, sizeof(on)); #endif /* TCP_NODELAY */ + #endif /* 0 */ #if defined(SO_LINGER) && defined(ENABLE_SO_LINGER) linger.l_onoff = 1; linger.l_linger = 15; *************** *** 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(); --- 892,898 ---- 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();