Blame SOURCES/cvs-1.11.22-ipv6-proxy.patch

83a95a
diff -up cvs-1.11.23/src/client.c.ipv6 cvs-1.11.23/src/client.c
83a95a
--- cvs-1.11.23/src/client.c.ipv6	2008-07-15 15:42:29.000000000 -0400
83a95a
+++ cvs-1.11.23/src/client.c	2008-07-15 15:43:46.000000000 -0400
83a95a
@@ -81,7 +81,7 @@ static Key_schedule sched;
83a95a
 /* This is needed for GSSAPI encryption.  */
83a95a
 static gss_ctx_id_t gcontext;
83a95a
 
83a95a
-static int connect_to_gserver PROTO((cvsroot_t *, int, struct hostent *));
83a95a
+static int connect_to_gserver PROTO((cvsroot_t *, int, char *));
83a95a
 
83a95a
 # endif /* HAVE_GSSAPI */
83a95a
 
83a95a
@@ -146,7 +146,7 @@ static size_t try_read_from_server PROTO
83a95a
 
83a95a
 static void proxy_connect PROTO ((cvsroot_t *, int));
83a95a
 static void auth_server PROTO ((cvsroot_t *, struct buffer *, struct buffer *,
83a95a
-				int, int, struct hostent *));
83a95a
+				int, int, char *));
83a95a
 
83a95a
 /* We need to keep track of the list of directories we've sent to the
83a95a
    server.  This list, along with the current CVSROOT, will help us
83a95a
@@ -3583,30 +3583,6 @@ supported_request (name)
83a95a
 
83a95a
 
83a95a
 #if defined (AUTH_CLIENT_SUPPORT) || defined (HAVE_KERBEROS) || defined (HAVE_GSSAPI)
83a95a
-static struct hostent *init_sockaddr PROTO ((struct sockaddr_in *, char *,
83a95a
-					     unsigned int));
83a95a
-
83a95a
-static struct hostent *
83a95a
-init_sockaddr (name, hostname, port)
83a95a
-    struct sockaddr_in *name;
83a95a
-    char *hostname;
83a95a
-    unsigned int port;
83a95a
-{
83a95a
-    struct hostent *hostinfo;
83a95a
-    unsigned short shortport = port;
83a95a
-
83a95a
-    memset (name, 0, sizeof (*name));
83a95a
-    name->sin_family = AF_INET;
83a95a
-    name->sin_port = htons (shortport);
83a95a
-    hostinfo = gethostbyname (hostname);
83a95a
-    if (hostinfo == NULL)
83a95a
-    {
83a95a
-	fprintf (stderr, "Unknown host %s.\n", hostname);
83a95a
-	error_exit ();
83a95a
-    }
83a95a
-    name->sin_addr = *(struct in_addr *) hostinfo->h_addr;
83a95a
-    return hostinfo;
83a95a
-}
83a95a
 
83a95a
 
83a95a
 
83a95a
@@ -3782,41 +3758,63 @@ connect_to_pserver (root, to_server_p, f
83a95a
 {
83a95a
     int sock;
83a95a
     int port_number;
83a95a
-    struct sockaddr_in client_sai;
83a95a
-    struct hostent *hostinfo;
83a95a
+    int gerr;
83a95a
+    struct addrinfo hints, *res, *res0;
83a95a
+    char pbuf[32];
83a95a
     struct buffer *local_to_server, *local_from_server;
83a95a
+    char *p_hostname;
83a95a
 
83a95a
-    sock = socket (AF_INET, SOCK_STREAM, 0);
83a95a
-    if (sock == -1)
83a95a
-    {
83a95a
-	error (1, 0, "cannot create socket: %s", SOCK_STRERROR (SOCK_ERRNO));
83a95a
-    }
83a95a
     port_number = get_cvs_port_number (root);
83a95a
 
83a95a
-    /* if we have a proxy connect to that instead */
83a95a
-    if (root->proxy_hostname)
83a95a
-    {
83a95a
-	hostinfo = init_sockaddr (&client_sai, root->proxy_hostname, root->proxy_port);
83a95a
-    }
83a95a
-    else
83a95a
-    {
83a95a
-	hostinfo = init_sockaddr (&client_sai, root->hostname, port_number);
83a95a
+    sprintf (pbuf, "%u", (root->proxy_hostname) ? root->proxy_port : port_number);
83a95a
+    pbuf[sizeof(pbuf)-1] = '\0';
83a95a
+    memset (&hints, 0, sizeof (hints));
83a95a
+    hints.ai_family = af;
83a95a
+    hints.ai_socktype = SOCK_STREAM;
83a95a
+
83a95a
+    /* do we have a proxy? */
83a95a
+    p_hostname = (root->proxy_hostname) ? root->proxy_hostname : root->hostname;
83a95a
+
83a95a
+    gerr = getaddrinfo (p_hostname, pbuf, &hints, &res0);
83a95a
+    if (gerr)
83a95a
+    {
83a95a
+       fprintf (stderr, "Unknown host %s.\n", p_hostname);
83a95a
+       error_exit ();
83a95a
+    }
83a95a
+
83a95a
+    /* Try connect to p_hostname using all available families */
83a95a
+    for (res = res0; res != NULL; res = res->ai_next)
83a95a
+    {
83a95a
+       sock = socket (res->ai_family, res->ai_socktype, 0);
83a95a
+       if (sock == -1) {
83a95a
+           if (res->ai_next)
83a95a
+               continue;
83a95a
+           else {
83a95a
+               char *sock_error = SOCK_STRERROR (SOCK_ERRNO);
83a95a
+               freeaddrinfo(res0);
83a95a
+               error (1, 0, "cannot create socket: %s", sock_error);
83a95a
+           }
83a95a
+       }
83a95a
+
83a95a
+       if (connect (sock, res->ai_addr, res->ai_addrlen) < 0)
83a95a
+       {
83a95a
+           if (res->ai_next)
83a95a
+           {
83a95a
+               close(sock);
83a95a
+               continue;
83a95a
+           }
83a95a
+           else
83a95a
+           {
83a95a
+               char *sock_error = SOCK_STRERROR (SOCK_ERRNO);
83a95a
+               freeaddrinfo(res0);
83a95a
+               error (1, 0, "connect to [%s]:%s failed: %s", p_hostname,
83a95a
+                       pbuf, sock_error);
83a95a
+           }
83a95a
+       }
83a95a
+       /* success */
83a95a
+       break;
83a95a
     }
83a95a
 
83a95a
-    if (trace)
83a95a
-    {
83a95a
-	fprintf (stderr, " -> Connecting to %s(%s):%d\n",
83a95a
-		 root->hostname,
83a95a
-		 inet_ntoa (client_sai.sin_addr), port_number);
83a95a
-    }
83a95a
-    if (connect (sock, (struct sockaddr *) &client_sai, sizeof (client_sai))
83a95a
-	< 0)
83a95a
-	error (1, 0, "connect to %s(%s):%d failed: %s",
83a95a
-	       root->proxy_hostname ? root->proxy_hostname : root->hostname,
83a95a
-	       inet_ntoa (client_sai.sin_addr),
83a95a
-	       root->proxy_hostname ? root->proxy_port : port_number,
83a95a
-	       SOCK_STRERROR (SOCK_ERRNO));
83a95a
-
83a95a
     make_bufs_from_fds (sock, sock, 0, &local_to_server, &local_from_server, 1);
83a95a
 
83a95a
     if (root->proxy_hostname)
83a95a
@@ -3830,7 +3828,7 @@ connect_to_pserver (root, to_server_p, f
83a95a
 	proxy_connect (root, port_number);
83a95a
     }
83a95a
 
83a95a
-    auth_server (root, local_to_server, local_from_server, verify_only, do_gssapi, hostinfo);
83a95a
+    auth_server (root, local_to_server, local_from_server, verify_only, do_gssapi, p_hostname);
83a95a
 
83a95a
     if (verify_only)
83a95a
     {
83a95a
@@ -3904,13 +3902,13 @@ proxy_connect (root, port_number)
83a95a
 
83a95a
 
83a95a
 static void
83a95a
-auth_server (root, lto_server, lfrom_server, verify_only, do_gssapi, hostinfo)
83a95a
+auth_server (root, lto_server, lfrom_server, verify_only, do_gssapi, hostname)
83a95a
     cvsroot_t *root;
83a95a
     struct buffer *lto_server;
83a95a
     struct buffer *lfrom_server;
83a95a
     int verify_only;
83a95a
     int do_gssapi;
83a95a
-    struct hostent *hostinfo;
83a95a
+    char *hostname;
83a95a
 {
83a95a
     char *username = "";		/* the username we use to connect */
83a95a
     char no_passwd = 0;			/* gets set if no password found */
83a95a
@@ -3940,7 +3938,7 @@ auth_server (root, lto_server, lfrom_ser
83a95a
 	    error (1, 0, "gserver currently only enabled for socket connections");
83a95a
 	}
83a95a
 
83a95a
-	if (! connect_to_gserver (root, fd, hostinfo))
83a95a
+	if (! connect_to_gserver (root, fd, hostname))
83a95a
 	{
83a95a
 	    error (1, 0,
83a95a
 		    "authorization failed: server %s rejected access to %s",
83a95a
@@ -3956,7 +3954,7 @@ auth_server (root, lto_server, lfrom_ser
83a95a
 	char *begin      = NULL;
83a95a
 	char *password   = NULL;
83a95a
 	char *end        = NULL;
83a95a
-	
83a95a
+
83a95a
 	if (verify_only)
83a95a
 	{
83a95a
 	    begin = "BEGIN VERIFICATION REQUEST";
83a95a
@@ -4137,36 +4135,74 @@ start_tcp_server (root, to_server, from_
83a95a
     int s;
83a95a
     const char *portenv;
83a95a
     int port;
83a95a
-    struct hostent *hp;
83a95a
-    struct sockaddr_in sin;
83a95a
+    int gerr;
83a95a
+    struct addrinfo hints, *res, *res0;
83a95a
     char *hname;
83a95a
-
83a95a
-    s = socket (AF_INET, SOCK_STREAM, 0);
83a95a
-    if (s < 0)
83a95a
-	error (1, 0, "cannot create socket: %s", SOCK_STRERROR (SOCK_ERRNO));
83a95a
+    char pbuf[32], hbuf[1025];
83a95a
 
83a95a
     port = get_cvs_port_number (root);
83a95a
 
83a95a
-    hp = init_sockaddr (&sin, root->hostname, port);
83a95a
+    sprintf (pbuf, "%u", port);
83a95a
+    pbuf[sizeof(pbuf)-1] = '\0';
83a95a
+    memset (&hints, 0, sizeof(hints));
83a95a
+    hints.ai_family = af;
83a95a
+    hints.ai_socktype = SOCK_STREAM;
83a95a
+    gerr = getaddrinfo (root->hostname, pbuf, &hints, &res0);
83a95a
+    if (gerr) {
83a95a
+	fprintf (stderr, "Unknown host %s.\n", root->hostname);
83a95a
+	error_exit ();
83a95a
+    }
83a95a
 
83a95a
-    hname = xstrdup (hp->h_name);
83a95a
-  
83a95a
-    if (trace)
83a95a
+    /* Try connect to current_parsed_root->hostname using all available families */
83a95a
+    gerr = -1;
83a95a
+    for (res = res0; res != NULL; res = res->ai_next)
83a95a
     {
83a95a
-	fprintf (stderr, " -> Connecting to %s(%s):%d\n",
83a95a
-		 root->hostname,
83a95a
-		 inet_ntoa (sin.sin_addr), port);
83a95a
+	s = socket (res->ai_family, res->ai_socktype, 0);
83a95a
+	if (s < 0)
83a95a
+	{
83a95a
+	    if (res->ai_next)
83a95a
+		continue;
83a95a
+	    else
83a95a
+	    {
83a95a
+		char *sock_error = SOCK_STRERROR (SOCK_ERRNO);
83a95a
+		freeaddrinfo(res0);
83a95a
+		error (1, 0, "cannot create socket: %s", sock_error);
83a95a
+	    }
83a95a
+	}
83a95a
+	if (trace)
83a95a
+	{
83a95a
+	    char hbuf[1025];
83a95a
+	    getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf),
83a95a
+		    NULL, 0, NI_NUMERICHOST);
83a95a
+	    fprintf (stderr, " -> Connecting to %s(%s):%d\n",
83a95a
+		    root->hostname, hbuf, port);
83a95a
+	}
83a95a
+	
83a95a
+	if (connect (s, res->ai_addr, res->ai_addrlen) < 0)
83a95a
+	{
83a95a
+	    if (res->ai_next)
83a95a
+	    {
83a95a
+		close(s);
83a95a
+		continue;
83a95a
+	    }
83a95a
+	    else
83a95a
+	    {
83a95a
+		char *sock_error = SOCK_STRERROR (SOCK_ERRNO);
83a95a
+		freeaddrinfo(res0);
83a95a
+		error (1, 0, "connect to [%s]:%s failed: %s",
83a95a
+			root->hostname, pbuf, sock_error);
83a95a
+	    }
83a95a
+	}
83a95a
+	getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf), NULL, 0, 0);
83a95a
+	hname = xmalloc (strlen (hbuf) + 1);
83a95a
+	strcpy (hname, hbuf);
83a95a
+	/* success */
83a95a
+	break;
83a95a
     }
83a95a
 
83a95a
-    if (connect (s, (struct sockaddr *) &sin, sizeof sin) < 0)
83a95a
-	error (1, 0, "connect to %s(%s):%d failed: %s",
83a95a
-	       root->hostname,
83a95a
-	       inet_ntoa (sin.sin_addr),
83a95a
-	       port, SOCK_STRERROR (SOCK_ERRNO));
83a95a
-
83a95a
     {
83a95a
 	const char *realm;
83a95a
-	struct sockaddr_in laddr;
83a95a
+	struct sockaddr_storage laddr;
83a95a
 	int laddrlen;
83a95a
 	KTEXT_ST ticket;
83a95a
 	MSG_DAT msg_data;
83a95a
@@ -4182,13 +4218,15 @@ start_tcp_server (root, to_server, from_
83a95a
 	/* We don't care about the checksum, and pass it as zero.  */
83a95a
 	status = krb_sendauth (KOPT_DO_MUTUAL, s, &ticket, "rcmd",
83a95a
 			       hname, realm, (unsigned long) 0, &msg_data,
83a95a
-			       &cred, sched, &laddr, &sin, "KCVSV1.0");
83a95a
+			       &cred, sched, &laddr, res->ai_addr, "KCVSV1.0");
83a95a
 	if (status != KSUCCESS)
83a95a
 	    error (1, 0, "kerberos authentication failed: %s",
83a95a
 		   krb_get_err_text (status));
83a95a
 	memcpy (kblock, cred.session, sizeof (C_Block));
83a95a
     }
83a95a
 
83a95a
+    freeaddrinfo(res0);
83a95a
+
83a95a
     close_on_exec (s);
83a95a
 
83a95a
     free (hname);
83a95a
@@ -4241,10 +4279,10 @@ recv_bytes (sock, buf, need)
83a95a
  */
83a95a
 #define BUFSIZE 1024
83a95a
 static int
83a95a
-connect_to_gserver (root, sock, hostinfo)
83a95a
+connect_to_gserver (root, sock, hostname)
83a95a
     cvsroot_t *root;
83a95a
     int sock;
83a95a
-    struct hostent *hostinfo;
83a95a
+    char *hostname;
83a95a
 {
83a95a
     char *str;
83a95a
     char buf[BUFSIZE];
83a95a
@@ -4257,9 +4295,9 @@ connect_to_gserver (root, sock, hostinfo
83a95a
     if (send (sock, str, strlen (str), 0) < 0)
83a95a
 	error (1, 0, "cannot send: %s", SOCK_STRERROR (SOCK_ERRNO));
83a95a
 
83a95a
-    if (strlen (hostinfo->h_name) > BUFSIZE - 5)
83a95a
+    if (strlen (hostname) > BUFSIZE - 5)
83a95a
 	error (1, 0, "Internal error: hostname exceeds length of buffer");
83a95a
-    sprintf (buf, "cvs@%s", hostinfo->h_name);
83a95a
+    sprintf (buf, "cvs@%s", hostname);
83a95a
     tok_in.length = strlen (buf);
83a95a
     tok_in.value = buf;
83a95a
     gss_import_name (&stat_min, &tok_in, GSS_C_NT_HOSTBASED_SERVICE,
83a95a
diff -up cvs-1.11.23/src/cvs.h.ipv6 cvs-1.11.23/src/cvs.h
83a95a
--- cvs-1.11.23/src/cvs.h.ipv6	2006-08-25 11:48:55.000000000 -0400
83a95a
+++ cvs-1.11.23/src/cvs.h	2008-07-15 15:42:29.000000000 -0400
83a95a
@@ -381,6 +381,7 @@ extern char *CurDir;
83a95a
 extern int really_quiet, quiet;
83a95a
 extern int use_editor;
83a95a
 extern int cvswrite;
83a95a
+extern int af;
83a95a
 extern mode_t cvsumask;
83a95a
 
83a95a
 
83a95a
diff -up cvs-1.11.23/src/main.c.ipv6 cvs-1.11.23/src/main.c
83a95a
--- cvs-1.11.23/src/main.c.ipv6	2008-07-15 15:42:28.000000000 -0400
83a95a
+++ cvs-1.11.23/src/main.c	2008-07-15 15:42:29.000000000 -0400
83a95a
@@ -18,6 +18,7 @@
83a95a
  */
83a95a
 
83a95a
 #include <assert.h>
83a95a
+#include <sys/socket.h>
83a95a
 #include "cvs.h"
83a95a
 
83a95a
 #ifdef HAVE_WINSOCK_H
83a95a
@@ -47,6 +48,7 @@ int quiet = 0;
83a95a
 int trace = 0;
83a95a
 int noexec = 0;
83a95a
 int logoff = 0;
83a95a
+int af = AF_UNSPEC;
83a95a
 
83a95a
 /*
83a95a
  * Zero if compression isn't supported or requested; non-zero to indicate
83a95a
@@ -164,7 +166,7 @@ static const char *const usg[] =
83a95a
        in --help as it is a rather different format from the rest.  */
83a95a
 
83a95a
     "Usage: %s [cvs-options] command [command-options-and-arguments]\n",
83a95a
-    "  where cvs-options are -q, -n, etc.\n",
83a95a
+    "  where cvs-options are -4, -6,-q, -n, etc.\n",
83a95a
     "    (specify --help-options for a list of options)\n",
83a95a
     "  where command is add, admin, etc.\n",
83a95a
     "    (specify --help-commands for a list of commands\n",
83a95a
@@ -262,6 +264,8 @@ static const char *const opt_usage[] =
83a95a
 #endif
83a95a
     "    -a           Authenticate all net traffic.\n",
83a95a
 #endif
83a95a
+    "    -4           Use IPv4.\n",
83a95a
+    "    -6           Use IPv6.\n",
83a95a
     "    -s VAR=VAL   Set CVS user variable.\n",
83a95a
     "(Specify the --help option for a list of other help options)\n",
83a95a
     NULL
83a95a
@@ -414,7 +418,7 @@ main (argc, argv)
83a95a
     int help = 0;		/* Has the user asked for help?  This
83a95a
 				   lets us support the `cvs -H cmd'
83a95a
 				   convention to give help for cmd. */
83a95a
-    static const char short_options[] = "+Qqrwtnvb:T:e:d:Hfz:s:xa";
83a95a
+    static const char short_options[] = "+46Qqrwtnvb:T:e:d:Hfz:s:xa";
83a95a
     static struct option long_options[] =
83a95a
     {
83a95a
         {"help", 0, NULL, 'H'},
83a95a
@@ -521,6 +525,12 @@ main (argc, argv)
83a95a
 		/* --allow-root */
83a95a
 		root_allow_add (optarg);
83a95a
 		break;
83a95a
+	    case '4':
83a95a
+		af = AF_INET;
83a95a
+		break;
83a95a
+	    case '6':
83a95a
+		af = AF_INET6;
83a95a
+		break;
83a95a
 	    case 'Q':
83a95a
 		really_quiet = 1;
83a95a
 		/* FALL THROUGH */
83a95a
diff -up cvs-1.11.23/src/server.c.ipv6 cvs-1.11.23/src/server.c
83a95a
--- cvs-1.11.23/src/server.c.ipv6	2008-07-15 15:42:29.000000000 -0400
83a95a
+++ cvs-1.11.23/src/server.c	2008-07-15 15:42:29.000000000 -0400
83a95a
@@ -6091,8 +6091,8 @@ kserver_authenticate_connection ()
83a95a
 {
83a95a
     int status;
83a95a
     char instance[INST_SZ];
83a95a
-    struct sockaddr_in peer;
83a95a
-    struct sockaddr_in laddr;
83a95a
+    struct sockaddr_storage peer;
83a95a
+    struct sockaddr_storage laddr;
83a95a
     int len;
83a95a
     KTEXT_ST ticket;
83a95a
     AUTH_DAT auth;
83a95a
@@ -6169,7 +6169,8 @@ static void
83a95a
 gserver_authenticate_connection ()
83a95a
 {
83a95a
     char hostname[MAXHOSTNAMELEN];
83a95a
-    struct hostent *hp;
83a95a
+    char hbuf[1025];
83a95a
+    struct addrinfo hints, *res0;
83a95a
     gss_buffer_desc tok_in, tok_out;
83a95a
     char buf[1024];
83a95a
     char *credbuf;
83a95a
@@ -6181,11 +6182,16 @@ gserver_authenticate_connection ()
83a95a
     gss_OID mechid;
83a95a
 
83a95a
     gethostname (hostname, sizeof hostname);
83a95a
-    hp = gethostbyname (hostname);
83a95a
-    if (hp == NULL)
83a95a
+    hostname[sizeof(hostname)-1] = '\0';
83a95a
+    memset (&hints, 0, sizeof(hints));
83a95a
+    hints.ai_family = af;
83a95a
+    hints.ai_socktype = SOCK_STREAM;
83a95a
+    hints.ai_flags = AI_CANONNAME;
83a95a
+    if (getaddrinfo (hostname, NULL, &hints, &res0))
83a95a
 	error (1, 0, "can't get canonical hostname");
83a95a
 
83a95a
-    sprintf (buf, "cvs@%s", hp->h_name);
83a95a
+    sprintf (buf, "cvs@%s", res0->ai_canonname);
83a95a
+    freeaddrinfo (res0);
83a95a
     tok_in.value = buf;
83a95a
     tok_in.length = strlen (buf);
83a95a