--- /dev/null
+diff -urN cvs-1.11.2.org/src/client.c cvs-1.11.2/src/client.c
+--- cvs-1.11.2.org/src/client.c Mon May 13 22:32:42 2002
++++ cvs-1.11.2/src/client.c Mon May 13 23:18:44 2002
+@@ -82,7 +82,7 @@
+ /* This is needed for GSSAPI encryption. */
+ static gss_ctx_id_t gcontext;
+
+-static int connect_to_gserver PROTO((cvsroot_t *, int, struct hostent *));
++static int connect_to_gserver PROTO((cvsroot_t *, int, char *));
+
+ # endif /* HAVE_GSSAPI */
+
+@@ -135,7 +135,7 @@
+ static size_t try_read_from_server PROTO ((char *, size_t));
+
+ static void auth_server PROTO ((cvsroot_t *, struct buffer *, struct buffer *,
+- int, int, struct hostent *));
++ int, int, char *));
+
+ /* We need to keep track of the list of directories we've sent to the
+ server. This list, along with the current CVSROOT, will help us
+@@ -3646,30 +3646,6 @@
+
+
+ #if defined (AUTH_CLIENT_SUPPORT) || defined (HAVE_KERBEROS) || defined (HAVE_GSSAPI)
+-static struct hostent *init_sockaddr PROTO ((struct sockaddr_in *, char *,
+- unsigned int));
+-
+-static struct hostent *
+-init_sockaddr (name, hostname, port)
+- struct sockaddr_in *name;
+- char *hostname;
+- unsigned int port;
+-{
+- struct hostent *hostinfo;
+- unsigned short shortport = port;
+-
+- memset (name, 0, sizeof (*name));
+- name->sin_family = AF_INET;
+- name->sin_port = htons (shortport);
+- hostinfo = gethostbyname (hostname);
+- if (hostinfo == NULL)
+- {
+- fprintf (stderr, "Unknown host %s.\n", hostname);
+- error_exit ();
+- }
+- name->sin_addr = *(struct in_addr *) hostinfo->h_addr;
+- return hostinfo;
+-}
+
+
+
+@@ -3871,34 +3841,59 @@
+ int do_gssapi;
+ {
+ int sock;
+- int port_number;
+- struct sockaddr_in client_sai;
+- struct hostent *hostinfo;
++ int gerr;
++ struct addrinfo hints, *res, *res0;
++ char pbuf[32];
+ struct buffer *to_server, *from_server;
+
+- sock = socket (AF_INET, SOCK_STREAM, 0);
+- if (sock == -1)
++ sprintf (pbuf, "%u", get_cvs_port_number (root));
++ pbuf[sizeof(pbuf)-1] = '\0';
++ memset (&hints, 0, sizeof (hints));
++ hints.ai_family = af;
++ hints.ai_socktype = SOCK_STREAM;
++ gerr = getaddrinfo (root->hostname, pbuf, &hints, &res0);
++ if (gerr)
+ {
+- error (1, 0, "cannot create socket: %s", SOCK_STRERROR (SOCK_ERRNO));
++ fprintf (stderr, "Unknown host %s.\n", root->hostname);
++ error_exit ();
+ }
+- port_number = get_cvs_port_number (root);
+- hostinfo = init_sockaddr (&client_sai, root->hostname, port_number);
+- if (trace)
++
++ /* Try connect to current_parsed_root->hostname using all available families */
++ for (res = res0; res != NULL; res = res->ai_next)
+ {
+- fprintf (stderr, " -> Connecting to %s(%s):%d\n",
+- root->hostname,
+- inet_ntoa (client_sai.sin_addr), port_number);
+- }
+- if (connect (sock, (struct sockaddr *) &client_sai, sizeof (client_sai))
+- < 0)
+- error (1, 0, "connect to %s(%s):%d failed: %s",
+- root->hostname,
+- inet_ntoa (client_sai.sin_addr),
+- port_number, SOCK_STRERROR (SOCK_ERRNO));
++ sock = socket (res->ai_family, res->ai_socktype, 0);
++ if (sock == -1) {
++ if (res->ai_next)
++ continue;
++ else {
++ char *sock_error = SOCK_STRERROR (SOCK_ERRNO);
++ freeaddrinfo(res0);
++ error (1, 0, "cannot create socket: %s", sock_error);
++ }
++ }
++
++ if (connect (sock, res->ai_addr, res->ai_addrlen) < 0)
++ {
++ if (res->ai_next)
++ {
++ close(sock);
++ continue;
++ }
++ else
++ {
++ char *sock_error = SOCK_STRERROR (SOCK_ERRNO);
++ freeaddrinfo(res0);
++ error (1, 0, "connect to [%s]:%s failed: %s", root->hostname,
++ pbuf, sock_error);
++ }
++ }
++ /* success */
++ break;
++ }
+
+ make_bufs_from_fds (sock, sock, 0, &to_server, &from_server, 1);
+
+- auth_server (root, to_server, from_server, verify_only, do_gssapi, hostinfo);
++ auth_server (root, to_server, from_server, verify_only, do_gssapi, root->hostname);
+
+ if (verify_only)
+ {
+@@ -3930,13 +3925,13 @@
+
+
+ static void
+-auth_server (root, lto_server, lfrom_server, verify_only, do_gssapi, hostinfo)
++auth_server (root, lto_server, lfrom_server, verify_only, do_gssapi, hostname)
+ cvsroot_t *root;
+ struct buffer *lto_server;
+ struct buffer *lfrom_server;
+ int verify_only;
+ int do_gssapi;
+- struct hostent *hostinfo;
++ char *hostname;
+ {
+ char *username; /* the username we use to connect */
+ char no_passwd = 0; /* gets set if no password found */
+@@ -3965,7 +3960,7 @@
+ error (1, 0, "gserver currently only enabled for socket connections");
+ }
+
+- if (! connect_to_gserver (root, fd, hostinfo))
++ if (! connect_to_gserver (root, fd, hostname))
+ {
+ error (1, 0,
+ "authorization failed: server %s rejected access to %s",
+@@ -3980,7 +3975,7 @@
+ char *begin = NULL;
+ char *password = NULL;
+ char *end = NULL;
+-
++
+ if (verify_only)
+ {
+ begin = "BEGIN VERIFICATION REQUEST";
+@@ -4117,37 +4112,76 @@
+ int s;
+ const char *portenv;
+ int port;
+- struct hostent *hp;
+- struct sockaddr_in sin;
++ int gerr;
++ struct addrinfo hints, *res, *res0;
+ char *hname;
+-
+- s = socket (AF_INET, SOCK_STREAM, 0);
+- if (s < 0)
+- error (1, 0, "cannot create socket: %s", SOCK_STRERROR (SOCK_ERRNO));
++ char pbuf[32], hbuf[1025];
+
+ port = get_cvs_port_number (root);
+
+- hp = init_sockaddr (&sin, root->hostname, port);
+-
+- hname = xmalloc (strlen (hp->h_name) + 1);
+- strcpy (hname, hp->h_name);
+-
+- if (trace)
++ sprintf (pbuf, "%u", port);
++ pbuf[sizeof(pbuf)-1] = '\0';
++ memset (&hints, 0, sizeof(hints));
++ hints.ai_family = af;
++ hints.ai_socktype = SOCK_STREAM;
++ gerr = getaddrinfo (root->hostname, pbuf, &hints, &res0);
++ if (gerr)
+ {
+- fprintf (stderr, " -> Connecting to %s(%s):%d\n",
+- root->hostname,
+- inet_ntoa (sin.sin_addr), port);
++ fprintf (stderr, "Unknown host %s.\n", root->hostname);
++ error_exit ();
+ }
+
+- if (connect (s, (struct sockaddr *) &sin, sizeof sin) < 0)
+- error (1, 0, "connect to %s(%s):%d failed: %s",
+- root->hostname,
+- inet_ntoa (sin.sin_addr),
+- port, SOCK_STRERROR (SOCK_ERRNO));
++ /* Try connect to current_parsed_root->hostname using all available families */
++ gerr = -1;
++ for (res = res0; res != NULL; res = res->ai_next)
++ {
++ s = socket (res->ai_family, res->ai_socktype, 0);
++ if (s < 0)
++ {
++ if (res->ai_next)
++ continue;
++ else
++ {
++ char *sock_error = SOCK_STRERROR (SOCK_ERRNO);
++ freeaddrinfo(res0);
++ error (1, 0, "cannot create socket: %s", sock_error);
++ }
++ }
++ if (trace)
++ {
++ char hbuf[1025];
++ getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf),
++ NULL, 0, NI_NUMERICHOST);
++ fprintf (stderr, " -> Connecting to %s(%s):%d\n",
++ root->hostname, hbuf, port);
++ }
++
++ if (connect (s, res->ai_addr, res->ai_addrlen) < 0)
++ {
++ if (res->ai_next)
++ {
++ close(s);
++ continue;
++ }
++ else
++ {
++ char *sock_error = SOCK_STRERROR (SOCK_ERRNO);
++ freeaddrinfo(res0);
++ error (1, 0, "connect to [%s]:%s failed: %s",
++ root->hostname, pbuf, sock_error);
++ }
++ }
++ getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf), NULL, 0, 0);
++ hname = xmalloc (strlen (hbuf) + 1);
++ strcpy (hname, hbuf);
++ /* success */
++ break;
++ }
++ freeaddrinfo(res0);
+
+ {
+ const char *realm;
+- struct sockaddr_in laddr;
++ struct sockaddr_storage laddr;
+ int laddrlen;
+ KTEXT_ST ticket;
+ MSG_DAT msg_data;
+@@ -4222,10 +4256,10 @@
+ */
+ #define BUFSIZE 1024
+ static int
+-connect_to_gserver (root, sock, hostinfo)
++connect_to_gserver (root, sock, hostname)
+ cvsroot_t *root;
+ int sock;
+- struct hostent *hostinfo;
++ char *hostname;
+ {
+ char *str;
+ char buf[BUFSIZE];
+@@ -4238,9 +4272,9 @@
+ if (send (sock, str, strlen (str), 0) < 0)
+ error (1, 0, "cannot send: %s", SOCK_STRERROR (SOCK_ERRNO));
+
+- if (strlen (hostinfo->h_name) > BUFSIZE - 5)
++ if (strlen (hostname) > BUFSIZE - 5)
+ error (1, 0, "Internal error: hostname exceeds length of buffer");
+- 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,
+diff -urN cvs-1.11.2.org/src/cvs.h cvs-1.11.2/src/cvs.h
+--- cvs-1.11.2.org/src/cvs.h Mon May 13 22:32:42 2002
++++ cvs-1.11.2/src/cvs.h Mon May 13 22:32:57 2002
+@@ -365,6 +365,7 @@
+ extern int really_quiet, quiet;
+ extern int use_editor;
+ extern int cvswrite;
++extern int af;
+ extern mode_t cvsumask;
+
+
+diff -urN cvs-1.11.2.org/src/main.c cvs-1.11.2/src/main.c
+--- cvs-1.11.2.org/src/main.c Mon May 13 22:32:42 2002
++++ cvs-1.11.2/src/main.c Mon May 13 22:32:57 2002
+@@ -13,6 +13,7 @@
+ */
+
+ #include <assert.h>
++#include <sys/socket.h>
+ #include "cvs.h"
+
+ #ifdef HAVE_WINSOCK_H
+@@ -42,6 +43,7 @@
+ int trace = 0;
+ int noexec = 0;
+ int logoff = 0;
++int af = AF_UNSPEC;
+
+ /* Set if we should be writing CVSADM directories at top level. At
+ least for now we'll make the default be off (the CVS 1.9, not CVS
+@@ -162,7 +164,7 @@
+ in --help as it is a rather different format from the rest. */
+
+ "Usage: %s [cvs-options] command [command-options-and-arguments]\n",
+- " where cvs-options are -q, -n, etc.\n",
++ " where cvs-options are -4, -6,-q, -n, etc.\n",
+ " (specify --help-options for a list of options)\n",
+ " where command is add, admin, etc.\n",
+ " (specify --help-commands for a list of commands\n",
+@@ -407,7 +409,7 @@
+ int help = 0; /* Has the user asked for help? This
+ lets us support the `cvs -H cmd'
+ convention to give help for cmd. */
+- static const char short_options[] = "+Qqrwtnlvb:T:e:d:Hfz:s:xa";
++ static const char short_options[] = "+46Qqrwtnlvb:T:e:d:Hfz:s:xa";
+ static struct option long_options[] =
+ {
+ {"help", 0, NULL, 'H'},
+@@ -520,6 +522,12 @@
+ /* --allow-root */
+ root_allow_add (optarg);
+ break;
++ case '4':
++ af = AF_INET;
++ break;
++ case '6':
++ af = AF_INET6;
++ break;
+ case 'Q':
+ really_quiet = 1;
+ /* FALL THROUGH */
+diff -urN cvs-1.11.2.org/src/server.c cvs-1.11.2/src/server.c
+--- cvs-1.11.2.org/src/server.c Mon May 13 22:32:42 2002
++++ cvs-1.11.2/src/server.c Mon May 13 22:32:57 2002
+@@ -5895,8 +5895,8 @@
+ {
+ int status;
+ char instance[INST_SZ];
+- struct sockaddr_in peer;
+- struct sockaddr_in laddr;
++ struct sockaddr_storage peer;
++ struct sockaddr_storage laddr;
+ int len;
+ KTEXT_ST ticket;
+ AUTH_DAT auth;
+@@ -5985,7 +5985,8 @@
+ gserver_authenticate_connection ()
+ {
+ char hostname[MAXHOSTNAMELEN];
+- struct hostent *hp;
++ char hbuf[1025];
++ struct addrinfo hints, *res0;
+ gss_buffer_desc tok_in, tok_out;
+ char buf[1024];
+ OM_uint32 stat_min, ret;
+@@ -5995,11 +5996,16 @@
+ gss_OID mechid;
+
+ gethostname (hostname, sizeof hostname);
+- hp = gethostbyname (hostname);
+- if (hp == NULL)
++ hostname[sizeof(hostname)-1] = '\0';
++ memset (&hints, 0, sizeof(hints));
++ hints.ai_family = af;
++ hints.ai_socktype = SOCK_STREAM;
++ hints.ai_flags = AI_CANONNAME;
++ if (getaddrinfo (hostname, NULL, &hints, &res))
+ error (1, 0, "can't get canonical hostname");
+
+- sprintf (buf, "cvs@%s", hp->h_name);
++ sprintf (buf, "cvs@%s", res0->ai_canonname);
++ freeaddrinfo (res0);
+ tok_in.value = buf;
+ tok_in.length = strlen (buf);
+