From 1d156a1800c61a8ea4ff92b85752893e8360dd5d Mon Sep 17 00:00:00 2001 From: Ben Kibbey Date: Sun, 29 Mar 2009 12:24:31 -0400 Subject: [PATCH] Added PWMD_OPTION_IP_VERSION which should be set to a pwmd_ip_version_t before trying to connect to an SSH host. This sets the IP version to use: PWMD_IPV4, PWMD_IPV6 or the default of PWMD_IP_ANY. Added pwmc command line options --ipv4, -4, --ipv6 and -6 to use this new option. --- src/libpwmd.c | 31 +++++++++++++++++++++++++++---- src/libpwmd.h.in | 14 ++++++++++++++ src/pwmc.c | 24 ++++++++++++++++++++++-- src/types.h | 1 + 4 files changed, 64 insertions(+), 6 deletions(-) diff --git a/src/libpwmd.c b/src/libpwmd.c index 99ddc1dc..558de4ec 100644 --- a/src/libpwmd.c +++ b/src/libpwmd.c @@ -479,17 +479,19 @@ static void dns_resolve_cb(void *arg, int status, int timeouts, return; } - //FIXME localhost. works with ipv4. maybe local system config error /* Check for an IPv6 address first. */ - rc = ares_parse_a_reply(abuf, alen, &he, NULL, NULL); + if (pwm->prot == PWMD_IP_ANY || pwm->prot == PWMD_IPV6) + rc = ares_parse_aaaa_reply(abuf, alen, &he, NULL, NULL); + else + rc = ares_parse_a_reply(abuf, alen, &he, NULL, NULL); if (rc != ARES_SUCCESS) { - if (rc != ARES_ENODATA) { + if (pwm->prot != PWMD_IP_ANY || rc != ARES_ENODATA) { pwm->tcp_conn->rc = ares_error_to_pwmd(status); return; } - rc = ares_parse_aaaa_reply(abuf, alen, &he, NULL, NULL); + rc = ares_parse_a_reply(abuf, alen, &he, NULL, NULL); if (rc != ARES_SUCCESS) { pwm->tcp_conn->rc = ares_error_to_pwmd(status); @@ -2294,6 +2296,24 @@ gpg_error_t pwmd_setopt(pwm_t *pwm, pwmd_option_t opt, ...) error = pwmd_command(pwm, &result, "OPTION LC_MESSAGES=%s", pwm->lcmessages); break; +#ifdef WITH_TCP + case PWMD_OPTION_IP_VERSION: + n = va_arg(ap, int); + + switch (n) { + case PWMD_IP_ANY: + case PWMD_IPV4: + case PWMD_IPV6: + pwm->prot = n; + break; + default: + error = GPG_ERR_INV_VALUE; + break; + } + + va_end(ap); + break; +#endif default: error = GPG_ERR_NOT_IMPLEMENTED; break; @@ -2351,6 +2371,9 @@ pwm_t *pwmd_new(const char *name) #ifdef WITH_PINENTRY h->nb_fd = -1; #endif +#ifdef WITH_TCP + h->prot = PWMD_IP_ANY; +#endif return h; } diff --git a/src/libpwmd.h.in b/src/libpwmd.h.in index e1c1b8d9..fd3460bf 100644 --- a/src/libpwmd.h.in +++ b/src/libpwmd.h.in @@ -44,6 +44,12 @@ typedef enum { ASYNC_DONE, } pwmd_async_t; +typedef enum { + PWMD_IP_ANY, + PWMD_IPV4, + PWMD_IPV6 +} pwmd_ip_version_t; + /* * A custom callback password retrieval function which is set with * pwmd_setopt(). This has priority over other retrieval methods if set. @@ -196,6 +202,14 @@ typedef enum { * Data passed to the status function. */ PWMD_OPTION_STATUS_DATA, + + /* + * PWMD_OPTION_IP_VERSION + * + * The protocol to use when doing DNS resolves. The argument should be a + * pwmd_ip_version_t. + */ + PWMD_OPTION_IP_VERSION, } pwmd_option_t; /* diff --git a/src/pwmc.c b/src/pwmc.c index 1b039598..8461fd10 100644 --- a/src/pwmc.c +++ b/src/pwmc.c @@ -83,6 +83,10 @@ static void usage(const char *pn, int status) " known host's file (for server validation)\n" " --get-hostkey, -g\n" " retrieve the remote SSH host key and exit\n" + " --ipv4, -4\n" + " try connecting via IPv4 only\n" + " --ipv6, -6\n" + " try connecting via IPv6 only\n" #endif " --timeout \n" " pinentry timeout\n" @@ -206,6 +210,7 @@ int main(int argc, char *argv[]) char *ident = NULL; char *known_hosts = NULL; int get = 0; + int prot = PWMD_IP_ANY; #endif int tries = 0; #ifdef DEBUG @@ -219,7 +224,7 @@ int main(int argc, char *argv[]) #endif #ifdef WITH_TCP OPT_HOST, OPT_PORT, OPT_IDENTITY, OPT_KNOWN_HOSTS, OPT_USER, - OPT_GET_HOSTKEY, + OPT_GET_HOSTKEY, OPT_IPV4, OPT_IPV6, #endif OPT_TTYNAME, OPT_TTYTYPE, OPT_DISPLAY, OPT_LC_CTYPE, OPT_LC_MESSAGES, OPT_TIMEOUT, OPT_TRIES, OPT_PINENTRY, @@ -237,6 +242,8 @@ int main(int argc, char *argv[]) { "known-hosts", 1, 0, 'k' }, { "user", 1, 0, 'u' }, { "get-hostkey", 0, 0, 'g' }, + { "ipv4", 0, 0, '4' }, + { "ipv6", 0, 0, '6' }, #endif { "ttyname", 1, 0, 'y' }, { "ttytype", 1, 0, 't' }, @@ -259,7 +266,7 @@ int main(int argc, char *argv[]) { 0, 0, 0, 0} }; #ifdef WITH_TCP - const char *optstring = "h:p:i:k:u:gy:t:d:P:I:Sn:"; + const char *optstring = "46h:p:i:k:u:gy:t:d:P:I:Sn:"; #else const char *optstring = "y:t:d:P:I:Sn:"; #endif @@ -331,6 +338,12 @@ int main(int argc, char *argv[]) break; #ifdef WITH_TCP + case '4': + prot = PWMD_IPV4; + break; + case '6': + prot = PWMD_IPV6; + break; case 'h': host = pwmd_strdup(optarg); break; @@ -397,6 +410,13 @@ int main(int argc, char *argv[]) #ifdef WITH_TCP if (host) { + if (prot != PWMD_IP_ANY) { + error = pwmd_setopt(pwm, PWMD_OPTION_IP_VERSION, prot); + + if (error) + goto done; + } + #ifdef DEBUG if (method) { if (get) { diff --git a/src/types.h b/src/types.h index 5d24d4e3..98cc02c4 100644 --- a/src/types.h +++ b/src/types.h @@ -65,6 +65,7 @@ struct pwm_s { assuan_context_t ctx; #ifdef WITH_TCP pwmd_tcp_conn_t *tcp_conn; + pwmd_ip_version_t prot; #endif int fd; pwmd_async_t state; -- 2.11.4.GIT