$NetBSD: patch-aq,v 1.1 2000/03/20 02:25:37 itojun Exp $ --- newchannels.c.orig Wed May 12 07:19:27 1999 +++ newchannels.c Fri Dec 24 22:01:15 1999 @@ -274,7 +274,7 @@ #include "authfd.h" #include "emulate.h" #include "servconf.h" -#ifdef LIBWRAP +#if defined(LIBWRAP) && defined(LIBWRAP_FWD) #include #include #ifdef NEED_SYS_SYSLOG_H @@ -922,6 +922,7 @@ /* This is our fake X11 server socket. */ if (FD_ISSET(ch->sock, readset)) { + int on = 1; debug("X11 connection requested."); addrlen = sizeof(addr); newsock = accept(ch->sock, &addr, &addrlen); @@ -930,11 +931,12 @@ error("accept: %.100s", strerror(errno)); break; } + setsockopt(newsock, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)); remote_hostname = get_remote_hostname(newsock); snprintf(buf, sizeof(buf), "X11 connection from %.200s port %d", remote_hostname, get_peer_port(newsock)); xfree(remote_hostname); -#ifdef LIBWRAP +#if defined(LIBWRAP) && defined(LIBWRAP_FWD) { struct request_info req; struct servent *serv; @@ -986,7 +988,7 @@ ch->listening_port, remote_hostname, get_peer_port(newsock)); xfree(remote_hostname); -#ifdef LIBWRAP +#if defined(LIBWRAP) && defined(LIBWRAP_FWD) { struct request_info req; struct servent *serv; @@ -1405,13 +1407,29 @@ int host_port, int gatewayports) { int ch, sock; - struct sockaddr_in sin; + struct addrinfo hints, *ai, *aitop; + char ntop[ADDRSTRLEN], strport[PORTSTRLEN]; if (strlen(host) > sizeof(channels[0].path) - 1) packet_disconnect("Forward host name too long."); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = IPv4or6; + hints.ai_flags = gatewayports ? AI_PASSIVE : 0; + hints.ai_socktype = SOCK_STREAM; + sprintf(strport, "%d", port); + if (getaddrinfo(NULL, strport, &hints, &aitop) != 0) + packet_disconnect("getaddrinfo: fatal error"); + + 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); + /* Create a port to listen for the host. */ - sock = socket(AF_INET, SOCK_STREAM, 0); + sock = socket(ai->ai_family, SOCK_STREAM, 0); if (sock < 0) packet_disconnect("socket: %.100s", strerror(errno)); @@ -1421,21 +1439,10 @@ (void)fcntl(sock, F_SETFL, O_NDELAY); #endif /* O_NONBLOCK && !O_NONBLOCK_BROKEN */ - /* Initialize socket address. */ - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - if (gatewayports) - sin.sin_addr.s_addr = INADDR_ANY; - else -#ifdef BROKEN_INET_ADDR - sin.sin_addr.s_addr = inet_network("127.0.0.1"); -#else /* BROKEN_INET_ADDR */ - sin.sin_addr.s_addr = inet_addr("127.0.0.1"); -#endif /* BROKEN_INET_ADDR */ - sin.sin_port = htons(port); - + debug("Listening on %s port %s.", ntop, strport); + /* Bind the socket to the address. */ - if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) + if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) packet_disconnect("bind: %.100s", strerror(errno)); /* Start listening for connections on the socket. */ @@ -1448,6 +1455,9 @@ strcpy(channels[ch].path, host); /* note: host name stored here */ channels[ch].host_port = host_port; /* port on host to connect to */ channels[ch].listening_port = port; /* port being listened */ + + } /* for (ai = aitop; ai; ai = ai->ai_next) */ + freeaddrinfo(aitop); } /* Initiate forwarding of connections to port "port" on remote host through @@ -1636,9 +1646,10 @@ void channel_input_port_open(void) { int remote_channel, sock, newch, host_port, i; - struct sockaddr_in sin; char *host, *originator_string; - struct hostent *hp; + struct addrinfo hints, *ai, *aitop; + char ntop[ADDRSTRLEN], strport[PORTSTRLEN]; + int gaierr; /* Get remote channel number. */ remote_channel = packet_get_int(); @@ -1678,36 +1689,15 @@ } } - memset(&sin, 0, sizeof(sin)); -#ifdef BROKEN_INET_ADDR - sin.sin_addr.s_addr = inet_network(host); -#else /* BROKEN_INET_ADDR */ - sin.sin_addr.s_addr = inet_addr(host); -#endif /* BROKEN_INET_ADDR */ - if ((sin.sin_addr.s_addr & 0xffffffff) != 0xffffffff) + memset(&hints, 0, sizeof(hints)); + hints.ai_family = IPv4or6; + hints.ai_socktype = SOCK_STREAM; + sprintf(strport, "%d", host_port); + if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) { - /* It was a valid numeric host address. */ - sin.sin_family = AF_INET; - } - else - { - /* Look up the host address from the name servers. */ - hp = gethostbyname(host); - if (!hp) - { - error("%.100s: unknown host.", host); - goto fail; - } - if (!hp->h_addr_list[0]) - { - error("%.100s: host has no IP address.", host); - goto fail; - } - sin.sin_family = hp->h_addrtype; - memcpy(&sin.sin_addr, hp->h_addr_list[0], - sizeof(sin.sin_addr)); + error("%.100s: unknown host (%s)", host, gai_strerror(gaierr)); + goto fail; } - sin.sin_port = htons(host_port); #ifdef F_SECURE_COMMERCIAL @@ -1744,8 +1734,15 @@ #endif /* F_SECURE_COMMERCIAL */ + 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); + /* Create the socket. */ - sock = socket(sin.sin_family, SOCK_STREAM, 0); + sock = socket(ai->ai_family, SOCK_STREAM, 0); if (sock < 0) { error("socket: %.100s", strerror(errno)); @@ -1753,15 +1750,25 @@ } /* Connect to the host/port. */ - if (connect(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) + if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0) { - error("connect %.100s:%d: %.100s", host, host_port, - strerror(errno)); + debug("connect %.100s port %s: %.100s", ntop, strport, strerror(errno)); close(sock); + continue; /* fail -- try next */ + } + break; /* success */ + + } /* for (ai = aitop; ai; ai = ai->ai_next) */ + freeaddrinfo(aitop); + + if (!ai) + { + error("connect %.100s:%d: failed.", host, host_port); goto fail; } /* Successful connection. */ + debug("Connecting to %.200s [%.100s] port %s.", host, ntop, strport); #if defined(O_NONBLOCK) && !defined(O_NONBLOCK_BROKEN) (void)fcntl(sock, F_SETFL, O_NONBLOCK); @@ -1803,7 +1810,10 @@ { extern ServerOptions options; int display_number, port, sock; - struct sockaddr_in sin; + struct addrinfo hints, *ai, *aitop; + char strport[PORTSTRLEN]; +#define NUM_SOCKS 10 + int gaierr, n, nn, num_socks = 0, socks[NUM_SOCKS]; char buf[512]; #ifdef HAVE_GETHOSTNAME char hostname[257]; @@ -1817,12 +1827,21 @@ for (display_number = options.x11_display_offset; display_number < MAX_DISPLAYS; display_number++) { port = 6000 + display_number; - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = INADDR_ANY; - sin.sin_port = htons(port); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = IPv4or6; + hints.ai_flags = AI_PASSIVE; + hints.ai_socktype = SOCK_STREAM; + sprintf(strport, "%d", port); + if ((gaierr = getaddrinfo(NULL, strport, &hints, &aitop)) != 0) + { + error("getaddrinfo: %.100s", gai_strerror(gaierr)); + return NULL; + } + + for (ai = aitop; ai; ai = ai->ai_next) + { - sock = socket(AF_INET, SOCK_STREAM, 0); + sock = socket(ai->ai_family, SOCK_STREAM, 0); if (sock < 0) { error("socket: %.100s", strerror(errno)); @@ -1835,13 +1854,26 @@ (void)fcntl(sock, F_SETFL, O_NDELAY); #endif /* O_NONBLOCK && !O_NONBLOCK_BROKEN */ - if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) + if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) { debug("bind port %d: %.100s", port, strerror(errno)); shutdown(sock, 2); close(sock); - continue; + for (n = 0; n < num_socks; n++) + { + shutdown(socks[n], 2); + close(socks[n]); + } + num_socks = 0; + break; } + + socks[num_socks++] = sock; + if (num_socks == NUM_SOCKS) + break; + } /* for (ai = aitop; ai; ai = ai->ai_next) */ + + if (num_socks > 0) break; } if (display_number >= MAX_DISPLAYS) @@ -1851,13 +1883,22 @@ } /* Start listening for connections on the socket. */ + for (n = 0; n < num_socks; n++) + { + sock = socks[n]; if (listen(sock, 5) < 0) { error("listen: %.100s", strerror(errno)); shutdown(sock, 2); close(sock); + for (nn = 0; nn < n; nn++) + { + shutdown(socks[nn], 2); + close(socks[nn]); + } return NULL; } + } /* for (n = 0; n < num_socks; n++) */ /* Set up a suitable value for the DISPLAY variable. */ #ifdef NONSTANDARD_IP_ADDRESS_X11_KLUDGE @@ -1868,10 +1909,11 @@ if (gethostname(hostname, sizeof(hostname)) < 0) fatal("gethostname: %.100s", strerror(errno)); { - struct hostent *hp; - struct in_addr addr; - hp = gethostbyname(hostname); - if (hp == NULL || !hp->h_addr_list[0]) + struct addrinfo hints, *ai; + char ntop[ADDRSTRLEN]; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = IPv4or6; + if (getaddrinfo(hostname, NULL, &hints, &ai) != 0 || !ai) { error("Could not get server IP address for %.200s.", hostname); packet_send_debug("Could not get server IP address for %.200s.", @@ -1880,9 +1922,10 @@ close(sock); return NULL; } - memcpy(&addr, hp->h_addr_list[0], sizeof(addr)); + getnameinfo(ai->ai_addr, ai->ai_addrlen, + ntop, sizeof(ntop), NULL, 0, NI_NUMERICHOST); snprintf(buf, sizeof(buf), - "%.100s:%d.%d", inet_ntoa(addr), display_number, + "%.100s:%d.%d", ntop, display_number, screen_number); } #else /* NONSTANDARD_IP_ADDRESS_X11_KLUDGE */ @@ -1900,8 +1943,12 @@ #endif /* NONSTANDARD_IP_ADDRESS_X11_KLUDGE */ /* Allocate a channel for the socket. */ + for (n = 0; n < num_socks; n++) + { + sock = socks[n]; (void)channel_allocate(SSH_CHANNEL_X11_LISTENER, sock, xstrdup("X11 inet listener")); + } /* for (n = 0; n < num_socks; n++) */ /* Return a suitable value for the DISPLAY environment variable. */ return xstrdup(buf); @@ -1916,9 +1963,10 @@ int remote_channel, display_number, sock, newch; const char *display; struct sockaddr_un ssun; - struct sockaddr_in sin; char buf[255], *cp, *remote_host; - struct hostent *hp; + struct addrinfo hints, *ai, *aitop; + char strport[PORTSTRLEN]; + int gaierr; /* Get remote channel number. */ remote_channel = packet_get_int(); @@ -2058,59 +2106,54 @@ goto fail; } - /* Try to parse the host name as a numeric IP address. */ - memset(&sin, 0, sizeof(sin)); -#ifdef BROKEN_INET_ADDR - sin.sin_addr.s_addr = inet_network(buf); -#else /* BROKEN_INET_ADDR */ - sin.sin_addr.s_addr = inet_addr(buf); -#endif /* BROKEN_INET_ADDR */ - if ((sin.sin_addr.s_addr & 0xffffffff) != 0xffffffff) + /* Look up the host address */ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = IPv4or6; + hints.ai_socktype = SOCK_STREAM; + sprintf(strport, "%d", 6000 + display_number); + if ((gaierr = getaddrinfo(buf, strport, &hints, &aitop)) != 0) { - /* It was a valid numeric host address. */ - sin.sin_family = AF_INET; + error("%.100s: unknown host. (%s)", buf, gai_strerror(gaierr)); + goto fail; } - else + + for (ai = aitop; ai; ai = ai->ai_next) { - /* 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. */ - sock = socket(sin.sin_family, SOCK_STREAM, 0); + sock = socket(ai->ai_family, SOCK_STREAM, 0); if (sock < 0) { - error("socket: %.100s", strerror(errno)); - goto fail; + debug("socket: %.100s", strerror(errno)); + continue; } /* 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:%d: %.100s", buf, 6000 + display_number, strerror(errno)); close(sock); + continue; + } + /* Success */ + break; + + } /* (ai = aitop, ai; ai = ai->ai_next) */ + freeaddrinfo(aitop); + if (!ai) + { + error("connect %.100s:%d: %.100s", buf, 6000 + display_number, + strerror(errno)); goto fail; } success: /* We have successfully obtained a connection to the real X display. */ - + { + int on = 1; + setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)); + } + #if defined(O_NONBLOCK) && !defined(O_NONBLOCK_BROKEN) (void)fcntl(sock, F_SETFL, O_NONBLOCK); #else /* O_NONBLOCK && !O_NONBLOCK_BROKEN */ @@ -2412,6 +2455,10 @@ ssh-agent connections on your system */ old_umask = umask(S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); + /* Make sure the socket doesn't already exist, left over from a system + crash perhaps. */ + unlink(channel_forwarded_auth_socket_name); + if (bind(sock, (struct sockaddr *)&sunaddr, AF_UNIX_SIZE(sunaddr)) < 0) packet_disconnect("Agent socket bind failed: %.100s", strerror(errno));