;; IPv6 support for CVS pserver of FreeBSD distribution ;; Nov 4, 2001 by Hajimu UMEMOTO Index: contrib/cvs/src/client.c diff -u contrib/cvs/src/client.c.orig contrib/cvs/src/client.c --- contrib/cvs/src/client.c.orig Mon Aug 20 17:47:21 2001 +++ contrib/cvs/src/client.c Sun Nov 4 01:24:02 2001 @@ -87,7 +87,7 @@ /* This is needed for GSSAPI encryption. */ static gss_ctx_id_t gcontext; -static int connect_to_gserver PROTO((int, struct hostent *)); +static int connect_to_gserver PROTO((int, const char *)); #endif /* HAVE_GSSAPI */ @@ -3868,35 +3868,55 @@ #endif int port_number; char *username; /* the username we use to connect */ - struct sockaddr_in client_sai; - struct hostent *hostinfo; char no_passwd = 0; /* gets set if no password found */ - - sock = socket (AF_INET, SOCK_STREAM, 0); - if (sock == -1) - { - error (1, 0, "cannot create socket: %s", SOCK_STRERROR (SOCK_ERRNO)); - } + struct addrinfo hints, *res, *res0 = NULL; + char hbuf[NI_MAXHOST], pbuf[10]; + int e; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_CANONNAME; port_number = get_cvs_port_number (current_parsed_root); - hostinfo = init_sockaddr (&client_sai, current_parsed_root->hostname, port_number); - if (trace) + snprintf(pbuf, sizeof(pbuf), "%d", port_number); + e = getaddrinfo(current_parsed_root->hostname, pbuf, &hints, &res0); + if (e) { - fprintf (stderr, " -> Connecting to %s(%s):%d\n", - current_parsed_root->hostname, - inet_ntoa (client_sai.sin_addr), port_number); + error (1, 0, "%s", gai_strerror(e)); } - if (connect (sock, (struct sockaddr *) &client_sai, sizeof (client_sai)) - < 0) - error (1, 0, "connect to %s(%s):%d failed: %s", + sock = -1; + for (res = res0; res; res = res->ai_next) { + if (trace) + { + getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf), + NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID); + fprintf (stderr, " -> Connecting to %s(%s):%d\n", + current_parsed_root->hostname, hbuf, port_number); + } + + sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (sock < 0) + continue; + + if (connect(sock, res->ai_addr, res->ai_addrlen) < 0) { + close(sock); + sock = -1; + continue; + } + break; + } + if (sock < 0) + { + error (1, 0, "connect to %s:%d failed: %s", current_parsed_root->hostname, - inet_ntoa (client_sai.sin_addr), port_number, SOCK_STRERROR (SOCK_ERRNO)); + } /* Run the authorization mini-protocol before anything else. */ if (do_gssapi) { #ifdef HAVE_GSSAPI - if (! connect_to_gserver (sock, hostinfo)) + if (! connect_to_gserver (sock, current_parsed_root->hostname)) { error (0, 0, "authorization failed: server %s rejected access to %s", @@ -4051,6 +4071,8 @@ if (shutdown (sock, 2) < 0) error (0, 0, "shutdown() failed, server %s: %s", current_parsed_root->hostname, SOCK_STRERROR (SOCK_ERRNO)); + if (res0) + freeaddrinfo(res0); return; } else @@ -4071,6 +4093,8 @@ #endif /* NO_SOCKET_TO_FD */ } + if (res0) + freeaddrinfo(res0); return; rejected: @@ -4194,9 +4218,9 @@ /* Connect to the server using GSSAPI authentication. */ static int -connect_to_gserver (sock, hostinfo) +connect_to_gserver (sock, hostname) int sock; - struct hostent *hostinfo; + const char *hostname; { char *str; char buf[1024]; @@ -4209,7 +4233,7 @@ if (send (sock, str, strlen (str), 0) < 0) error (1, 0, "cannot send: %s", SOCK_STRERROR (SOCK_ERRNO)); - sprintf (buf, "cvs@%s", hostinfo->h_name); + sprintf (buf, "cvs@%s", hostname); tok_in.length = strlen (buf); tok_in.value = buf; gss_import_name (&stat_min, &tok_in, GSS_C_NT_HOSTBASED_SERVICE, Index: contrib/cvs/src/server.c diff -u contrib/cvs/src/server.c.orig contrib/cvs/src/server.c --- contrib/cvs/src/server.c.orig Fri Aug 10 18:53:06 2001 +++ contrib/cvs/src/server.c Sat Nov 3 23:16:06 2001 @@ -5879,19 +5879,20 @@ { int status; char instance[INST_SZ]; - struct sockaddr_in peer; - struct sockaddr_in laddr; - int len; + struct sockaddr_storage peer; + struct sockaddr_storage laddr; + int plen, llen; KTEXT_ST ticket; AUTH_DAT auth; char version[KRB_SENDAUTH_VLEN]; char user[ANAME_SZ]; strcpy (instance, "*"); - len = sizeof peer; - if (getpeername (STDIN_FILENO, (struct sockaddr *) &peer, &len) < 0 + plen = sizeof peer; + llen = sizeof laddr; + if (getpeername (STDIN_FILENO, (struct sockaddr *) &peer, &plen) < 0 || getsockname (STDIN_FILENO, (struct sockaddr *) &laddr, - &len) < 0) + &llen) < 0) { printf ("E Fatal error, aborting.\n\ error %s getpeername or getsockname failed\n", strerror (errno));