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

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