Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/Remmina/Remmina.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorStephane Coulondre <stephane@coulondre.info>2023-06-20 20:16:24 +0300
committerStephane Coulondre <stephane@coulondre.info>2023-06-20 20:16:24 +0300
commit13309ef940d728c2d8bd0e10abe0191042dc685c (patch)
tree88f4969661a0e668bdc1342dd9dc387cca39a3a9 /src
parent3e440b4e36f2def0aa2efdc2ae3bd1c0db42f254 (diff)
Solved issue #2910 - Added support for IPv6 with fallback to IPv4 for ssh
Diffstat (limited to 'src')
-rw-r--r--src/remmina_ssh.c62
1 files changed, 59 insertions, 3 deletions
diff --git a/src/remmina_ssh.c b/src/remmina_ssh.c
index a5c9101ce..d5c6f1115 100644
--- a/src/remmina_ssh.c
+++ b/src/remmina_ssh.c
@@ -1672,6 +1672,12 @@ remmina_ssh_init_session(RemminaSSH *ssh)
socket_t sshsock;
gint optval;
#endif
+ // Handle IPv4 / IPv6 dual stack
+ char *hostname;
+ struct addrinfo hints,*aitop,*ai;
+ char ipstr[INET6_ADDRSTRLEN];
+ void *addr4=NULL;
+ void *addr6=NULL;
ssh->callback = g_new0(struct ssh_callbacks_struct, 1);
@@ -1840,12 +1846,62 @@ remmina_ssh_init_session(RemminaSSH *ssh)
else
REMMINA_DEBUG("SSH_OPTIONS_COMPRESSION does not have a valid value. %s", ssh->compression);
- if (ssh_connect(ssh->session)) {
- // TRANSLATORS: The placeholder %s is an error message
- remmina_ssh_set_error(ssh, _("Could not start SSH session. %s"));
+ // Handle the dual IPv4 / IPv6 stack
+ // Prioritize IPv6 and fallback to IPv4
+
+ // Run the DNS resolution
+ // First retrieve host from the ssh->session structure
+ ssh_options_get(ssh->session, SSH_OPTIONS_HOST, &hostname);
+ // Call getaddrinfo
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ if ((getaddrinfo(hostname, NULL, &hints, &aitop)) != 0) {
+ ssh->error = g_strdup_printf("Could not resolve hostname %s", hostname);
+ REMMINA_DEBUG(ssh->error);
return FALSE;
}
+ // We have one or more addesses now, extract them
+ ai = aitop;
+ while (ai != NULL) {
+ if (ai->ai_family == AF_INET) { // IPv4
+ struct sockaddr_in *ipv4 = (struct sockaddr_in *)ai->ai_addr;
+ addr4 = &(ipv4->sin_addr);
+ } else { // IPv6
+ struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)ai->ai_addr;
+ addr6 = &(ipv6->sin6_addr);
+ }
+ ai = ai->ai_next;
+ }
+ freeaddrinfo(aitop);
+
+ unsigned short int success6 = 0;
+ if (addr6 != NULL) {
+ // Try IPv6 first
+ inet_ntop(AF_INET6, addr6, ipstr, sizeof ipstr);
+ ssh_options_set(ssh->session, SSH_OPTIONS_HOST, ipstr);
+ REMMINA_DEBUG("Setting SSH_OPTIONS_HOST to IPv6 %s", ipstr);
+ if (ssh_connect(ssh->session)) {
+ ssh_disconnect(ssh->session);
+ REMMINA_DEBUG("IPv6 session failed");
+ } else {
+ success6 = 1;
+ REMMINA_DEBUG("IPv6 session success !");
+ }
+ }
+ if (success6 == 0) {
+ // Fallback to IPv4
+ inet_ntop(AF_INET, addr4, ipstr, sizeof ipstr);
+ ssh_options_set(ssh->session, SSH_OPTIONS_HOST, ipstr);
+ REMMINA_DEBUG("Setting SSH_OPTIONS_HOST to IPv4 %s", ipstr);
+ if (ssh_connect(ssh->session)) {
+ // TRANSLATORS: The placeholder %s is an error message
+ remmina_ssh_set_error(ssh, _("Could not start SSH session. %s"));
+ return FALSE;
+ }
+ }
+
#ifdef HAVE_NETINET_TCP_H
/* Set keepalive on SSH socket, so we can keep firewalls awaken and detect
* when we loss the tunnel */