session CHANGE always store ip-address host in the session
Fixes cesnet/netopeer2#382
diff --git a/src/session_client.c b/src/session_client.c
index 5ddb6bc..738fbb1 100644
--- a/src/session_client.c
+++ b/src/session_client.c
@@ -1310,18 +1310,20 @@
has to be invoked, until it returns a valid socket.
*/
int
-nc_sock_connect(const char* host, uint16_t port, int timeout, int* sock_pending)
+nc_sock_connect(const char *host, uint16_t port, int timeout, int *sock_pending, char **ip_host)
{
int i;
- int sock = sock_pending?*sock_pending:-1;
+ int sock = sock_pending ? *sock_pending : -1;
struct addrinfo hints, *res_list, *res;
char port_s[6]; /* length of string representation of short int */
+ char *buf;
+ void *addr;
- VRB("nc_sock_connect(%s, %u, %d, %d)", host, port, timeout, sock);
+ DBG("nc_sock_connect(%s, %u, %d, %d)", host, port, timeout, sock);
/* no pending socket */
if (sock == -1) {
- /* Connect to a server */
+ /* connect to a server */
snprintf(port_s, 6, "%u", port);
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
@@ -1340,6 +1342,27 @@
continue;
}
VRB("Successfully connected to %s:%s over %s.", host, port_s, (res->ai_family == AF_INET6) ? "IPv6" : "IPv4");
+ if (ip_host && ((res->ai_family == AF_INET6) || (res->ai_family == AF_INET))) {
+ buf = malloc(INET6_ADDRSTRLEN);
+ if (!buf) {
+ ERRMEM;
+ close(sock);
+ return -1;
+ }
+ if (res->ai_family == AF_INET) {
+ addr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
+ } else {
+ addr = &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
+ }
+ if (!inet_ntop(res->ai_family, addr, buf, INET6_ADDRSTRLEN)) {
+ ERR("Converting host to IP address failed (%s).", strerror(errno));
+ free(buf);
+ close(sock);
+ return -1;
+ }
+
+ *ip_host = buf;
+ }
break;
}
freeaddrinfo(res_list);
diff --git a/src/session_client_ssh.c b/src/session_client_ssh.c
index b0ba9dd..4319517 100644
--- a/src/session_client_ssh.c
+++ b/src/session_client_ssh.c
@@ -1489,7 +1489,7 @@
static struct nc_session *
_nc_connect_libssh(ssh_session ssh_session, struct ly_ctx *ctx, struct nc_client_ssh_opts *opts, int timeout)
{
- char *host = NULL, *username = NULL;
+ char *host = NULL, *username = NULL, *ip_host;
unsigned short port = 0;
int sock;
struct passwd *pw;
@@ -1528,13 +1528,16 @@
ssh_options_set(session->ti.libssh.session, SSH_OPTIONS_HOST, host);
/* create and connect socket */
- sock = nc_sock_connect(host, port, -1, NULL);
+ sock = nc_sock_connect(host, port, -1, NULL, &ip_host);
if (sock == -1) {
ERR("Unable to connect to %s:%u (%s).", host, port, strerror(errno));
goto fail;
}
ssh_options_set(session->ti.libssh.session, SSH_OPTIONS_FD, &sock);
ssh_set_blocking(session->ti.libssh.session, 0);
+
+ free(host);
+ host = ip_host;
}
/* was username set? */
@@ -1622,7 +1625,7 @@
const long timeout = NC_SSH_TIMEOUT;
int sock;
uint32_t port_uint;
- char *username;
+ char *username, *ip_host = NULL;
struct passwd *pw;
struct nc_session *session = NULL;
@@ -1675,7 +1678,7 @@
"ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-rsa,rsa-sha2-512,rsa-sha2-256,ssh-dss");
/* create and assign communication socket */
- sock = nc_sock_connect(host, port, -1, NULL);
+ sock = nc_sock_connect(host, port, -1, NULL, &ip_host);
if (sock == -1) {
ERR("Unable to connect to %s:%u (%s).", host, port, strerror(errno));
goto fail;
@@ -1707,13 +1710,14 @@
}
/* store information into the dictionary */
- session->host = lydict_insert(ctx, host, 0);
+ session->host = lydict_insert_zc(ctx, ip_host);
session->port = port;
session->username = lydict_insert(ctx, username, 0);
return session;
fail:
+ free(ip_host);
nc_session_free(session, NULL);
return NULL;
}
diff --git a/src/session_client_tls.c b/src/session_client_tls.c
index 5611aba..71bb134 100644
--- a/src/session_client_tls.c
+++ b/src/session_client_tls.c
@@ -581,6 +581,7 @@
struct nc_session *session = NULL;
int sock, verify, ret;
struct timespec ts_timeout, ts_cur;
+ char *ip_host = NULL;
if (!tls_opts.cert_path || (!tls_opts.ca_file && !tls_opts.ca_dir)) {
ERRINIT;
@@ -617,7 +618,7 @@
}
/* create and assign socket */
- sock = nc_sock_connect(host, port, -1, NULL);
+ sock = nc_sock_connect(host, port, -1, NULL, &ip_host);
if (sock == -1) {
ERR("Unable to connect to %s:%u (%s).", host, port, strerror(errno));
goto fail;
@@ -680,13 +681,14 @@
}
/* store information into session and the dictionary */
- session->host = lydict_insert(ctx, host, 0);
+ session->host = lydict_insert_zc(ctx, ip_host);
session->port = port;
session->username = lydict_insert(ctx, "certificate-based", 0);
return session;
fail:
+ free(ip_host);
nc_session_free(session, NULL);
return NULL;
}
diff --git a/src/session_p.h b/src/session_p.h
index 3397d78..367cd29 100644
--- a/src/session_p.h
+++ b/src/session_p.h
@@ -546,10 +546,11 @@
* @param[in] host Hostname to connect to.
* @param[in] port Port to connect on.
* @param[in] timeout for blocking the connect+select call (-1 for infinite).
- * @param[in] sock_pending for exchanging the pending socket, if the blocking timeout was != -1
+ * @param[in,out] sock_pending for exchanging the pending socket, if the blocking timeout was != -1
+ * @param[out] ip_host Optional parameter with string IP address of the connected host.
* @return Connected socket or -1 on error.
*/
-int nc_sock_connect(const char *host, uint16_t port, int timeout, int* sock_pending);
+int nc_sock_connect(const char *host, uint16_t port, int timeout, int* sock_pending, char **ip_host);
/**
* @brief Accept a new socket connection.
diff --git a/src/session_server.c b/src/session_server.c
index f49b491..8caaf13 100644
--- a/src/session_server.c
+++ b/src/session_server.c
@@ -901,7 +901,7 @@
if ((ETIMEDOUT == ret) && (ps->queue[ps->queue_begin] == *id)) {
break;
}
-
+
ERR("%s: failed to wait for a pollsession condition (%s).", func, strerror(ret));
/* remove ourselves from the queue */
nc_ps_queue_remove_id(ps, *id);
@@ -2844,8 +2844,9 @@
NC_MSG_TYPE msgtype;
int sock, ret;
struct timespec ts_cur;
+ char *ip_host;
- sock = nc_sock_connect(endpt->address, endpt->port, 5, &endpt->sock_pending);
+ sock = nc_sock_connect(endpt->address, endpt->port, 5, &endpt->sock_pending, &ip_host);
if (sock < 0) {
return NC_MSG_ERROR;
}
@@ -2856,12 +2857,13 @@
if (!(*session)) {
ERRMEM;
close(sock);
+ free(ip_host);
return NC_MSG_ERROR;
}
(*session)->status = NC_STATUS_STARTING;
(*session)->ctx = server_opts.ctx;
(*session)->flags = NC_SESSION_SHAREDCTX;
- (*session)->host = lydict_insert(server_opts.ctx, endpt->address, 0);
+ (*session)->host = lydict_insert_zc(server_opts.ctx, ip_host);
(*session)->port = endpt->port;
/* sock gets assigned to session or closed */