;; IPv6 support for CVS pserver of FreeBSD 5-CURRENT distribution ;; Sep 7, 2002 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 Sep 2 14:57:13 2002 +++ contrib/cvs/src/client.c Sat Sep 7 04:48:54 2002 @@ -86,7 +86,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, const char *)); # endif /* HAVE_GSSAPI */ @@ -139,7 +139,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, struct addrinfo *)); /* 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 @@ -3682,6 +3682,8 @@ #ifdef AUTH_CLIENT_SUPPORT +static int auth_server_port_number PROTO ((void)); + /* Generic function to do port number lookup tasks. * * In order of precedence, will return: @@ -3876,33 +3878,53 @@ { int sock; int port_number; - struct sockaddr_in client_sai; - struct hostent *hostinfo; + char *username; /* the username we use to connect */ + struct addrinfo hints, *res, *res0 = NULL; + char pbuf[10], aibuf[NI_MAXHOST]; + int e; struct buffer *to_server, *from_server; - sock = socket (AF_INET, SOCK_STREAM, 0); - if (sock == -1) - { - error (1, 0, "cannot create socket: %s", SOCK_STRERROR (SOCK_ERRNO)); - } + 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 (root); - hostinfo = init_sockaddr (&client_sai, root->hostname, port_number); - if (trace) + snprintf(pbuf, sizeof(pbuf), "%d", port_number); + e = getaddrinfo(root->hostname, pbuf, &hints, &res0); + if (e) + { + error (1, 0, "%s", gai_strerror(e)); + } + sock = -1; + for (res = res0; res; res = res->ai_next) { + sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + getnameinfo(res->ai_addr, res->ai_addr->sa_len, + aibuf, sizeof(aibuf), NULL, 0, NI_NUMERICHOST); + if (sock < 0) + continue; + + if (trace) + { + fprintf (stderr, " -> Connecting to %s(%s):%d\n", + root->hostname, aibuf, port_number); + } + if (connect(sock, res->ai_addr, res->ai_addrlen) < 0) { + close(sock); + sock = -1; + continue; + } + break; + } + if (sock < 0) { - fprintf (stderr, " -> Connecting to %s(%s):%d\n", - root->hostname, - inet_ntoa (client_sai.sin_addr), port_number); + error (1, 0, "connect to %s(%s):%s failed: %s", + root->hostname, aibuf, pbuf, + SOCK_STRERROR (SOCK_ERRNO)); } - 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)); 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, res0); if (verify_only) { @@ -3927,20 +3949,21 @@ *to_server_p = to_server; *from_server_p = from_server; } - + if (res0) + freeaddrinfo(res0); return; } 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, res0) cvsroot_t *root; struct buffer *lto_server; struct buffer *lfrom_server; int verify_only; int do_gssapi; - struct hostent *hostinfo; + struct addrinfo *res0; { char *username; /* the username we use to connect */ char no_passwd = 0; /* gets set if no password found */ @@ -3969,7 +3992,8 @@ error (1, 0, "gserver currently only enabled for socket connections"); } - if (! connect_to_gserver (root, fd, hostinfo)) + if (! connect_to_gserver (root, fd, + res0->ai_canonname ? res0->ai_canonname : root->hostname)) { error (1, 0, "authorization failed: server %s rejected access to %s", @@ -4226,10 +4250,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; + int sock; + const char *hostname; { char *str; char buf[BUFSIZE]; @@ -4242,9 +4266,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, 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 Mon Sep 2 14:57:14 2002 +++ contrib/cvs/src/server.c Sat Sep 7 04:48:54 2002 @@ -5905,19 +5905,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));