Skip Menu |
 

From: Sam Hartman <hartmans@debian.org>
To: krb5-bugs@mit.edu
Subject: IPv6 support for kprop and kpropd
Date: Wed, 17 Mar 2010 20:14:15 -0400
Show quoted text
>From 186285ea06792068d634f7855f9737595d2b7e53 Mon Sep 17 00:00:00 2001
From: Michael Stapelberg <michael@stapelberg.de>
Date: Tue, 16 Mar 2010 22:39:55 +0100
Subject: [PATCH 1/2] Implement support for IPv6 (kprop)

---
src/slave/Makefile.in | 8 ++--
src/slave/kprop.c | 85 ++++++++++++++++++++++++++----------------------
src/slave/kprop.h | 2 +
src/slave/kprop_sock.c | 39 ++++++++++++++++++++++
4 files changed, 91 insertions(+), 43 deletions(-)
create mode 100644 src/slave/kprop_sock.c

diff --git a/src/slave/Makefile.in b/src/slave/Makefile.in
index 20bef7c..6630562 100644
--- a/src/slave/Makefile.in
+++ b/src/slave/Makefile.in
@@ -6,11 +6,11 @@ DEFS=

all:: kprop kpropd kproplog

-CLIENTSRCS= $(srcdir)/kprop.c
-CLIENTOBJS= kprop.o
+CLIENTSRCS= $(srcdir)/kprop.c $(srcdir)/kprop_sock.c
+CLIENTOBJS= kprop.o kprop_sock.o

-SERVERSRCS= $(srcdir)/kpropd.c $(srcdir)/kpropd_rpc.c
-SERVEROBJS= kpropd.o kpropd_rpc.o
+SERVERSRCS= $(srcdir)/kpropd.c $(srcdir)/kpropd_rpc.c $(srcdir)/kprop_sock.c
+SERVEROBJS= kpropd.o kpropd_rpc.o kprop_sock.o

LOGSRCS= $(srcdir)/kproplog.c
LOGOBJS= kproplog.o
diff --git a/src/slave/kprop.c b/src/slave/kprop.c
index dffb99a..53d933b 100644
--- a/src/slave/kprop.c
+++ b/src/slave/kprop.c
@@ -319,53 +319,56 @@ open_connection(host, fd, Errmsg, ErrmsgSz)
unsigned int ErrmsgSz;
{
int s;
- krb5_error_code retval;
-
- struct hostent *hp;
- register struct servent *sp;
- struct sockaddr_in my_sin;
+ krb5_error_code retval = 1;
GETSOCKNAME_ARG3_TYPE socket_length;
-
- hp = gethostbyname(host);
- if (hp == NULL) {
- (void) snprintf(Errmsg, ErrmsgSz, "%s: unknown host", host);
+ struct addrinfo hints, *res, *answers;
+ struct sockaddr *sa;
+ struct sockaddr_storage my_sin;
+ int error;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ if ((error = getaddrinfo(host, KPROP_SERVICE, &hints, &answers)) != 0) {
+ (void) snprintf(Errmsg, ErrmsgSz, "%s: %s", host, gai_strerror(error));
*fd = -1;
return(0);
}
- my_sin.sin_family = hp->h_addrtype;
- memcpy(&my_sin.sin_addr, hp->h_addr, sizeof(my_sin.sin_addr));
- if(!port) {
- sp = getservbyname(KPROP_SERVICE, "tcp");
- if (sp == 0) {
- my_sin.sin_port = htons(KPROP_PORT);
- } else {
- my_sin.sin_port = sp->s_port;
+ for (res = answers; res != NULL; res = res->ai_next) {
+ s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+ if (s < 0) {
+ (void) snprintf(Errmsg, ErrmsgSz, "in call to socket");
+ freeaddrinfo(answers);
+ return(errno);
+ }
+ if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
+ retval = errno;
+ close(s);
+ s = -1;
+ continue;
}
- } else
- my_sin.sin_port = port;
- s = socket(AF_INET, SOCK_STREAM, 0);

- if (s < 0) {
- (void) snprintf(Errmsg, ErrmsgSz, "in call to socket");
- return(errno);
+ /* We successfully connect()ed */
+ *fd = s;
+ if (sockaddr2krbaddr(res->ai_family, res->ai_addr, &receiver_addr) != 0) {
+ (void) snprintf(Errmsg, ErrmsgSz, "Bad address family");
+ *fd = -1;
+ return(0);
+ }
+
+ break;
}
- if (connect(s, (struct sockaddr *)&my_sin, sizeof my_sin) < 0) {
- retval = errno;
- close(s);
+
+ freeaddrinfo(answers);
+
+ if (s == -1) {
(void) snprintf(Errmsg, ErrmsgSz, "in call to connect");
return(retval);
}
- *fd = s;

/*
- * Set receiver_addr and sender_addr.
+ * Set sender_addr.
*/
- receiver_addr.addrtype = ADDRTYPE_INET;
- receiver_addr.length = sizeof(my_sin.sin_addr);
- receiver_addr.contents = (krb5_octet *) malloc(sizeof(my_sin.sin_addr));
- memcpy(receiver_addr.contents, &my_sin.sin_addr,
- sizeof(my_sin.sin_addr));
-
socket_length = sizeof(my_sin);
if (getsockname(s, (struct sockaddr *)&my_sin, &socket_length) < 0) {
retval = errno;
@@ -373,11 +376,15 @@ open_connection(host, fd, Errmsg, ErrmsgSz)
(void) snprintf(Errmsg, ErrmsgSz, "in call to getsockname");
return(retval);
}
- sender_addr.addrtype = ADDRTYPE_INET;
- sender_addr.length = sizeof(my_sin.sin_addr);
- sender_addr.contents = (krb5_octet *) malloc(sizeof(my_sin.sin_addr));
- memcpy(sender_addr.contents, &my_sin.sin_addr,
- sizeof(my_sin.sin_addr));
+
+ sa = (struct sockaddr *) &my_sin;
+
+ if (sockaddr2krbaddr(sa->sa_family, sa, &sender_addr) != 0) {
+ (void) snprintf(Errmsg, ErrmsgSz, "Bad address family");
+ close(s);
+ *fd = -1;
+ return(0);
+ }

return(0);
}
diff --git a/src/slave/kprop.h b/src/slave/kprop.h
index 4ab53de..263f138 100644
--- a/src/slave/kprop.h
+++ b/src/slave/kprop.h
@@ -37,3 +37,5 @@
#define KPROP_BUFSIZ 32768

/* pathnames are in osconf.h, included via k5-int.h */
+
+int sockaddr2krbaddr(int family, struct sockaddr *sa, krb5_address *dest);
diff --git a/src/slave/kprop_sock.c b/src/slave/kprop_sock.c
new file mode 100644
index 0000000..ed477a5
--- /dev/null
+++ b/src/slave/kprop_sock.c
@@ -0,0 +1,39 @@
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "k5-int.h"
+#include "kprop.h"
+
+int sockaddr2krbaddr(int family, struct sockaddr *sa, krb5_address *dest)
+{
+ struct sockaddr_in *sa4;
+ struct sockaddr_in6 *sa6;
+
+ if (family == AF_INET) {
+ dest->addrtype = ADDRTYPE_INET;
+ sa4 = (struct sockaddr_in *)sa;
+ dest->length = sizeof(sa4->sin_addr);
+ dest->contents = (krb5_octet *) malloc(sizeof(sa4->sin_addr));
+ if (!dest->contents) {
+ (void) fprintf(stderr, _("\nCouldn't allocate memory"));
+ exit(1);
+ }
+ memcpy(dest->contents, &sa4->sin_addr, sizeof(sa4->sin_addr));
+ return 0;
+ } else if (family == AF_INET6) {
+ dest->addrtype = ADDRTYPE_INET6;
+ sa6 = (struct sockaddr_in6 *)sa;
+ dest->length = sizeof(sa6->sin6_addr);
+ dest->contents = (krb5_octet *) malloc(sizeof(sa6->sin6_addr));
+ if (!dest->contents) {
+ (void) fprintf(stderr, _("\nCouldn't allocate memory"));
+ exit(1);
+ }
+ memcpy(dest->contents, &sa6->sin6_addr, sizeof(sa6->sin6_addr));
+ return 0;
+ }
+
+ /* Bad address family */
+ return 1;
+}
--
1.6.5

>From e9a3a1e239831f57ec18e877c6274ac34671273b Mon Sep 17 00:00:00 2001
From: Michael Stapelberg <michael@stapelberg.de>
Date: Tue, 16 Mar 2010 23:39:38 +0100
Subject: [PATCH 2/2] Implement IPv6 support (kpropd)

---
src/slave/kpropd.c | 174 +++++++++++++++++++++++-----------------------------
1 files changed, 78 insertions(+), 96 deletions(-)

diff --git a/src/slave/kpropd.c b/src/slave/kpropd.c
index e3bcd68..0672655 100644
--- a/src/slave/kpropd.c
+++ b/src/slave/kpropd.c
@@ -162,7 +162,7 @@ void kerberos_authenticate(
int,
krb5_principal *,
krb5_enctype *,
- struct sockaddr_in);
+ struct sockaddr_storage *);
krb5_boolean authorized_principal(krb5_context, krb5_principal, krb5_enctype);
void recv_database(krb5_context, int, int, krb5_data *);
void load_database(krb5_context, char *, char *);
@@ -242,10 +242,10 @@ static void resync_alarm(int sn)
int do_standalone(iprop_role iproprole)
{
struct sockaddr_in my_sin, frominet;
- struct servent *sp;
+ struct addrinfo hints, *res, *answers;
int finet, s;
GETPEERNAME_ARG3_TYPE fromlen;
- int ret;
+ int ret, error;
/*
* Timer for accept/read calls, in case of network type errors.
*/
@@ -253,92 +253,86 @@ int do_standalone(iprop_role iproprole)

retry:

- finet = socket(AF_INET, SOCK_STREAM, 0);
- if (finet < 0) {
- com_err(progname, errno, "while obtaining socket");
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE;
+
+ if ((error = getaddrinfo(NULL, KPROP_SERVICE, &hints, &answers)) != 0) {
+ (void) fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(error));
exit(1);
}
- memset(&my_sin,0, sizeof(my_sin));
- if(!port) {
- sp = getservbyname(KPROP_SERVICE, "tcp");
- if (sp == NULL) {
- com_err(progname, 0, "%s/tcp: unknown service", KPROP_SERVICE);
- my_sin.sin_port = htons(KPROP_PORT);
+
+ for (res = answers; res != NULL; res = res->ai_next) {
+ finet = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+ if (finet < 0) {
+ com_err(progname, errno, "while obtaining socket");
+ exit(1);
}
- else my_sin.sin_port = sp->s_port;
- } else {
- my_sin.sin_port = port;
- }
- my_sin.sin_family = AF_INET;

- /*
- * We need to close the socket immediately if iprop is enabled,
- * since back-to-back full resyncs are possible, so we do not
- * linger around for too long
- */
- if (iproprole == IPROP_SLAVE) {
int on = 1;
- struct linger linger;
+ if (setsockopt (finet, SOL_SOCKET, SO_REUSEADDR,
+ (void *)&on, sizeof(on)) < 0)
+ com_err(progname, errno,
+ _("while setting socket option (SO_REUSEADDR)"));

- if (setsockopt(finet, SOL_SOCKET, SO_REUSEADDR,
- (char *)&on, sizeof(on)) < 0)
- com_err(progname, errno,
- _("while setting socket option (SO_REUSEADDR)"));
- linger.l_onoff = 1;
- linger.l_linger = 2;
- if (setsockopt(finet, SOL_SOCKET, SO_LINGER,
- (void *)&linger, sizeof(linger)) < 0)
- com_err(progname, errno,
- _("while setting socket option (SO_LINGER)"));
/*
- * We also want to set a timer so that the slave is not waiting
- * until infinity for an update from the master.
+ * We need to close the socket immediately if iprop is enabled,
+ * since back-to-back full resyncs are possible, so we do not
+ * linger around for too long
*/
- gfd = finet;
- signal(SIGALRM, resync_alarm);
- if (debug) {
- fprintf(stderr, "do_standalone: setting resync alarm to %d\n",
- backoff_timer);
- }
- if (alarm(backoff_timer) != 0) {
+ if (iproprole == IPROP_SLAVE) {
+ struct linger linger;
+
+ linger.l_onoff = 1;
+ linger.l_linger = 2;
+ if (setsockopt(finet, SOL_SOCKET, SO_LINGER,
+ (void *)&linger, sizeof(linger)) < 0)
+ com_err(progname, errno,
+ _("while setting socket option (SO_LINGER)"));
+ /*
+ * We also want to set a timer so that the slave is not waiting
+ * until infinity for an update from the master.
+ */
+ gfd = finet;
+ signal(SIGALRM, resync_alarm);
if (debug) {
- fprintf(stderr,
- _("%s: alarm already set\n"), progname);
+ fprintf(stderr, "do_standalone: setting resync alarm to %d\n",
+ backoff_timer);
}
+ if (alarm(backoff_timer) != 0) {
+ if (debug) {
+ fprintf(stderr,
+ _("%s: alarm already set\n"), progname);
+ }
+ }
+ backoff_timer *= 2;
}
- backoff_timer *= 2;
- }
- if ((ret = bind(finet, (struct sockaddr *) &my_sin, sizeof(my_sin))) < 0) {
- if (debug) {
- int on = 1;
- fprintf(stderr,
- "%s: attempting to rebind socket with SO_REUSEADDR\n",
- progname);
- if (setsockopt(finet, SOL_SOCKET, SO_REUSEADDR,
- (char *)&on, sizeof(on)) < 0)
- com_err(progname, errno, "in setsockopt(SO_REUSEADDR)");
- ret = bind(finet, (struct sockaddr *) &my_sin, sizeof(my_sin));
- }
- if (ret < 0) {
+
+ if ((ret = bind(finet, res->ai_addr, res->ai_addrlen)) < 0) {
perror("bind");
com_err(progname, errno, "while binding listener socket");
exit(1);
}
- }
- if (!debug && iproprole != IPROP_SLAVE)
- daemon(1, 0);
+ if (!debug && iproprole != IPROP_SLAVE)
+ daemon(1, 0);
#ifdef PID_FILE
- if ((pidfile = fopen(PID_FILE, "w")) != NULL) {
- fprintf(pidfile, "%d\n", getpid());
- fclose(pidfile);
- } else
- com_err(progname, errno,
- "while opening pid file %s for writing", PID_FILE);
+ if ((pidfile = fopen(PID_FILE, "w")) != NULL) {
+ fprintf(pidfile, "%d\n", getpid());
+ fclose(pidfile);
+ } else
+ com_err(progname, errno,
+ "while opening pid file %s for writing", PID_FILE);
#endif
- if (listen(finet, 5) < 0) {
- com_err(progname, errno, "in listen call");
- exit(1);
+
+ if (listen(finet, 5) < 0) {
+ com_err(progname, errno, "in listen call");
+ exit(1);
+ }
+ break;
}
+
while (1) {
int child_pid;
int status;
@@ -419,16 +413,16 @@ retry:
void doit(fd)
int fd;
{
- struct sockaddr_in from;
+ struct sockaddr_storage from;
int on = 1;
GETPEERNAME_ARG3_TYPE fromlen;
- struct hostent *hp;
krb5_error_code retval;
krb5_data confmsg;
int lock_fd;
mode_t omask;
krb5_enctype etype;
int database_fd;
+ char host[INET6_ADDRSTRLEN+1];

if (kpropd_context->kdblog_context &&
kpropd_context->kdblog_context->iproprole == IPROP_SLAVE) {
@@ -468,23 +462,19 @@ void doit(fd)
"while attempting setsockopt (SO_KEEPALIVE)");
}

- if (!(hp = gethostbyaddr((char *) &(from.sin_addr.s_addr), fromlen,
- AF_INET))) {
- syslog(LOG_INFO, "Connection from %s",
- inet_ntoa(from.sin_addr));
- if (debug)
- printf("Connection from %s\n",
- inet_ntoa(from.sin_addr));
- } else {
- syslog(LOG_INFO, "Connection from %s", hp->h_name);
+
+ if (getnameinfo((const struct sockaddr *) &from, fromlen,
+ host, sizeof(host), NULL, 0, 0) == 0) {
+ syslog(LOG_INFO, "Connection from %s", host);
if (debug)
- printf("Connection from %s\n", hp->h_name);
+ printf("Connection from %s\n", host);
}

+
/*
* Now do the authentication
*/
- kerberos_authenticate(kpropd_context, fd, &client, &etype, from);
+ kerberos_authenticate(kpropd_context, fd, &client, &etype, &from);

/*
* Turn off alarm upon successful authentication from master.
@@ -1216,22 +1206,18 @@ kerberos_authenticate(context, fd, clientp, etype, my_sin)
int fd;
krb5_principal * clientp;
krb5_enctype * etype;
- struct sockaddr_in my_sin;
+ struct sockaddr_storage * my_sin;
{
krb5_error_code retval;
krb5_ticket * ticket;
- struct sockaddr_in r_sin;
+ struct sockaddr_storage r_sin;
GETSOCKNAME_ARG3_TYPE sin_length;
krb5_keytab keytab = NULL;

/*
* Set recv_addr and send_addr
*/
- sender_addr.addrtype = ADDRTYPE_INET;
- sender_addr.length = sizeof(my_sin.sin_addr);
- sender_addr.contents = (krb5_octet *) malloc(sizeof(my_sin.sin_addr));
- memcpy(sender_addr.contents, &my_sin.sin_addr,
- sizeof(my_sin.sin_addr));
+ sockaddr2krbaddr(my_sin->ss_family, my_sin, &sender_addr);

sin_length = sizeof(r_sin);
if (getsockname(fd, (struct sockaddr *) &r_sin, &sin_length)) {
@@ -1239,11 +1225,7 @@ kerberos_authenticate(context, fd, clientp, etype, my_sin)
exit(1);
}

- receiver_addr.addrtype = ADDRTYPE_INET;
- receiver_addr.length = sizeof(r_sin.sin_addr);
- receiver_addr.contents = (krb5_octet *) malloc(sizeof(r_sin.sin_addr));
- memcpy(receiver_addr.contents, &r_sin.sin_addr,
- sizeof(r_sin.sin_addr));
+ sockaddr2krbaddr(r_sin.ss_family, &r_sin, &receiver_addr);

if (debug) {
char *name;
--
1.6.5

[hartmans@debian.org - Wed Mar 17 20:14:34 2010]:

Show quoted text

corrected URL:

http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=549476
Download (untitled) / with headers
text/plain 3.2KiB
From krb5-bugs-incoming-bounces@PCH.mit.edu Wed May 26 15:00:47 2010
Return-Path: <krb5-bugs-incoming-bounces@PCH.mit.edu>
Received: from pch.mit.edu (PCH.MIT.EDU [18.7.21.90])
by krbdev.mit.edu (Postfix) with ESMTP id 027DD3E716;
Wed, 26 May 2010 15:00:46 -0400 (EDT)
Received: from pch.mit.edu (pch.mit.edu [127.0.0.1])
by pch.mit.edu (8.13.6/8.12.8) with ESMTP id o4QJ0kfD016158;
Wed, 26 May 2010 15:00:46 -0400
Received: from mailhub-dmz-2.mit.edu (MAILHUB-DMZ-2.MIT.EDU [18.7.62.37])
by pch.mit.edu (8.13.6/8.12.8) with ESMTP id o4QIxSAQ015949
for <krb5-bugs-incoming@PCH.mit.edu>; Wed, 26 May 2010 14:59:28 -0400
Received: from dmz-mailsec-scanner-8.mit.edu (DMZ-MAILSEC-SCANNER-8.MIT.EDU
[18.7.68.37])
by mailhub-dmz-2.mit.edu (8.13.8/8.9.2) with ESMTP id o4QIwuLv013971
for <krb5-bugs@mit.edu>; Wed, 26 May 2010 14:59:27 -0400
X-AuditID: 12074425-b7d00ae000002295-44-4bfd6f8f92ec
Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28])
by dmz-mailsec-scanner-8.mit.edu (Symantec Brightmail Gateway) with
SMTP id 6F.22.08853.F8F6DFB4; Wed, 26 May 2010 14:59:27 -0400 (EDT)
Received: from int-mx04.intmail.prod.int.phx2.redhat.com
(int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.17])
by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o4QIxQ7p020490
(version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK)
for <krb5-bugs@mit.edu>; Wed, 26 May 2010 14:59:26 -0400
Received: from blade.bos.redhat.com (blade.bos.redhat.com [10.16.0.23])
by int-mx04.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP
id o4QIxPhh022769
(version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO)
for <krb5-bugs@mit.edu>; Wed, 26 May 2010 14:59:26 -0400
Received: from blade.bos.redhat.com (blade.bos.redhat.com [127.0.0.1])
by blade.bos.redhat.com (8.14.4/8.14.3) with ESMTP id o4QIxPDW007550
for <krb5-bugs@mit.edu>; Wed, 26 May 2010 14:59:25 -0400
Received: (from nalin@localhost)
by blade.bos.redhat.com (8.14.4/8.14.4/Submit) id o4QIxOOe007548;
Wed, 26 May 2010 14:59:24 -0400
Date: Wed, 26 May 2010 14:59:24 -0400
Message-Id: <201005261859.o4QIxOOe007548@blade.bos.redhat.com>
To: krb5-bugs@mit.edu
Subject: kprop and kpropd don't support IPv6
From: nalin@redhat.com
X-send-pr-version: 3.99
X-Scanned-By: MIMEDefang 2.67 on 10.5.11.17
X-Brightmail-Tracker: AAAAARRkZHk=
X-Mailman-Approved-At: Wed, 26 May 2010 15:00:45 -0400
X-BeenThere: krb5-bugs-incoming@mailman.mit.edu
X-Mailman-Version: 2.1.6
Precedence: list
Sender: krb5-bugs-incoming-bounces@PCH.mit.edu
Errors-To: krb5-bugs-incoming-bounces@PCH.mit.edu

Show quoted text
>Submitter-Id: net
>Originator:
>Organization:
>Confidential: no
>Synopsis: kprop and kpropd don't support IPv6
>Severity: non-critical
>Priority: medium
>Category: krb5-admin
>Class: change-request
>Release: 1.8.1
>Environment:

System: Linux blade.bos.redhat.com 2.6.33.3-85.fc13.x86_64 #1 SMP Thu May 6 18:09:49 UTC 2010 x86_64 x86_64 x86_64 GNU/Linux
Architecture: x86_64

Show quoted text
>Description:
The kprop client uses IPv4-only APIs when contacting a kprop server,
and kpropd only expects IPv4 sockets when run either via inetd or in
standalone mode.
Show quoted text
>How-To-Repeat:
Set up kpropd on an IPv6-capable host and make sure that the only
address the client can find is an IPv6 address. The client will fail
to resolve the address, and the server will only bind to an IPv4
socket in standalone mode.
There is a patch for this from a Debian user at
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=549476 although it has
some issues.

Unfortunately I do not have an IPv6 testing environment. If I clean up
the patch and commit it to trunk, do you have the necessary facilities to
test it in an IPv6 environment?
Date: Mon, 7 Jun 2010 15:34:53 -0400
From: Nalin Dahyabhai <nalin@redhat.com>
To: rt@krbdev.mit.edu
Subject: Re: [krbdev.mit.edu #6735] kprop and kpropd don't support IPv6
RT-Send-Cc:
On Mon, Jun 07, 2010 at 03:20:04PM -0400, Greg Hudson via RT wrote:
Show quoted text
> There is a patch for this from a Debian user at
> http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=549476 although it has
> some issues.
>
> Unfortunately I do not have an IPv6 testing environment. If I clean up
> the patch and commit it to trunk, do you have the necessary facilities to
> test it in an IPv6 environment?

I believe so, yes.

Thanks,

Nalin
From: ghudson@mit.edu
Subject: SVN Commit

Use getaddrinfo() in kprop and kpropd, and recognize IPv6 addresses
when setting up krb5_address structures. kpropd still only binds to
one socket to avoid the need for a select() loop, so we turn off
IPV6_V6ONLY on that socket to ensure that IPv4 connections will still
be accepted.

Based on a patch from Michael Stapelberg <michael@stapelberg.de>.


https://github.com/krb5/krb5/commit/c58f231b1a988eecc99e73f8394f298bf1d2a166
Commit By: ghudson
Revision: 24134
Changed Files:
U trunk/src/slave/Makefile.in
U trunk/src/slave/kprop.c
U trunk/src/slave/kprop.h
A trunk/src/slave/kprop_sock.c
U trunk/src/slave/kpropd.c
Date: Mon, 28 Jun 2010 14:15:21 -0400
From: Nalin Dahyabhai <nalin@redhat.com>
To: rt@krbdev.mit.edu
Subject: Re: [krbdev.mit.edu #6735] kprop and kpropd don't support IPv6
RT-Send-Cc:
Download (untitled) / with headers
text/plain 2.4KiB
The kprop client seems to be working well, but kpropd currently gives me
this warning when run in standalone mode:
kpropd: Protocol not available while unsetting IPV6_V6ONLY option

This appears to happen because getaddrinfo() is returning a list of two
addresses (the first is the IPv4 wildcard address, and the second is the
IPv6 wildcard address), and kpropd is only using the first.

Checking that res->ai_family is AF_INET6 before calling setsockopt() at
line 277 suppresses the warning, but then it's still listening only for
IPv4 connections.

I've found that asking getaddrinfo() for an AF_INET6 address with
AI_ADDRCONFIG added to hints.ai_flags seems to reliably return an error
when IPv6 isn't supported, and falling back from there to asking for an
AF_INET address, while not particularly elegant, seems to do the job.

HTH,

Nalin

Index: src/slave/kpropd.c
===================================================================
--- src/slave/kpropd.c (revision 24148)
+++ src/slave/kpropd.c (working copy)
@@ -250,14 +250,22 @@
retry:

memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_UNSPEC;
+ hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags = AI_PASSIVE;
+ hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG | AI_V4MAPPED;

error = getaddrinfo(NULL, port, &hints, &res);
if (error != 0) {
- (void) fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(error));
- exit(1);
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
+
+ error = getaddrinfo(NULL, port, &hints, &res);
+ if (error != 0) {
+ (void) fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(error));
+ exit(1);
+ }
}

finet = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
@@ -274,8 +282,9 @@
/* Typically, res will be the IPv6 wildcard address. Some systems, such as
* the *BSDs, don't accept IPv4 connections on this address by default. */
val = 0;
- if (setsockopt(finet, IPPROTO_IPV6, IPV6_V6ONLY, &val, sizeof(val)) < 0)
- com_err(progname, errno, "while unsetting IPV6_V6ONLY option");
+ if (res->ai_family == AF_INET6)
+ if (setsockopt(finet, IPPROTO_IPV6, IPV6_V6ONLY, &val, sizeof(val)) < 0)
+ com_err(progname, errno, "while unsetting IPV6_V6ONLY option");
#endif

/*
We have reason to believe (from code inspection) that OpenBSD doesn't
support dual-stack IPv6 sockets in its default configuration. That means
we're going to have to introduce a select loop to make standalone mode
work. I should have a patch ready in a few days, ideally.
Opening two listener sockets in kpropd is more difficult than I expected,
because of the complicated iprop logic. So I'm committing a variation of
your patch.

Why did you add AI_V4MAPPED to hints in the first getaddrinfo query?
From: ghudson@mit.edu
Subject: SVN Commit

In kpropd, when getting a wildcard address to listen on, try IPv6
explicitly (with AI_ADDRCONFIG specified where available, to avoid
IPv6 on hosts with no IPv6 interface) and then fall back to IPv4.
Only set IPV6_V6ONLY on the listener socket if the resulting address
is IPv6.

Note: we have mostly confirmed that OpenBSD does not have dual-stack
support, meaning that it would be better to open separate IPv4 and
IPv6 listener sockets, as we do in krb5kdc and kadmind.
Unfortunately, the complicated iprop retry-and-backoff logic makes
this less than straightforward.


https://github.com/krb5/krb5/commit/3ecdc07603dfa6acc4604abfc5c2e0274204746d
Commit By: ghudson
Revision: 24156
Changed Files:
U trunk/src/slave/kpropd.c
Date: Thu, 1 Jul 2010 14:06:23 -0400
From: Nalin Dahyabhai <nalin@redhat.com>
To: rt@krbdev.mit.edu
Subject: Re: [krbdev.mit.edu #6686] IPv6 support for kprop and kpropd
RT-Send-Cc:
On Thu, Jul 01, 2010 at 12:42:12PM -0400, Greg Hudson via RT wrote:
Show quoted text
> Opening two listener sockets in kpropd is more difficult than I expected,
> because of the complicated iprop logic. So I'm committing a variation of
> your patch.
>
> Why did you add AI_V4MAPPED to hints in the first getaddrinfo query?

It's more or less a leftover. It didn't actually have any effect on my
test machine, but it puts that call to getaddrinfo() more in line with
the behavior glibc follows when the hints structure is NULL (which is to
behave as if the supplied flags were (AI_V4MAPPED | AI_ADDRCONFIG)).

Nalin
From: Sam Hartman <hartmans@debian.org>
To: rt@krbdev.mit.edu
Subject: Re: [krbdev.mit.edu #6686] IPv6 support for kprop and kpropd
Date: Thu, 01 Jul 2010 19:23:48 -0400
RT-Send-Cc:
As an FYI, I do care somewhat about FreeBSD support, but I do know that
FreeBSD supports v6only.
Individually, I have no need for OpenBSD support.