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: 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
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