Skip to content

Commit

Permalink
Support IPv6 (rscada#213)
Browse files Browse the repository at this point in the history
* Rewritten TCP connection to support IPv6 and get rid of deprecated gethostbyname

Signed-off-by: Petr Kracík <petrkr@petrkr.net>

(cherry picked from commit cb28aca)
  • Loading branch information
petrkr authored and Apollon77 committed Mar 26, 2024
1 parent 0293238 commit 827241a
Showing 1 changed file with 30 additions and 22 deletions.
52 changes: 30 additions & 22 deletions mbus/mbus-tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ typedef SSIZE_T ssize_t;
#else
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <strings.h>
#endif
Expand All @@ -50,6 +48,7 @@ typedef SSIZE_T ssize_t;
#include "mbus-tcp.h"

#define PACKET_BUFF_SIZE 2048
#define MAX_PORT_SIZE 6 // Size of port number + NULL char

static int tcp_timeout_sec = 4;
static int tcp_timeout_usec = 0;
Expand All @@ -61,11 +60,11 @@ int
mbus_tcp_connect(mbus_handle *handle)
{
char error_str[128], *host;
struct hostent *host_addr;
struct sockaddr_in s;
struct addrinfo hints, *servinfo, *p;
struct timeval time_out;
mbus_tcp_data *tcp_data;
uint16_t port;
char port[MAX_PORT_SIZE];
int status;

if (handle == NULL)
return -1;
Expand All @@ -75,7 +74,7 @@ mbus_tcp_connect(mbus_handle *handle)
return -1;

host = tcp_data->host;
port = tcp_data->port;
snprintf(port, MAX_PORT_SIZE, "%d", tcp_data->port);

#ifdef _WIN32
WORD wVersionRequested;
Expand All @@ -94,32 +93,41 @@ mbus_tcp_connect(mbus_handle *handle)
return -1;
}
#endif
//
// create the TCP connection
//
if ((handle->fd = socket(AF_INET,SOCK_STREAM, 0)) < 0)

memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;

if ((status = getaddrinfo(host, port, &hints, &servinfo)) != 0)
{
snprintf(error_str, sizeof(error_str), "%s: failed to setup a socket.", __PRETTY_FUNCTION__);
snprintf(error_str, sizeof(error_str), "%s: getaddrinfo: %s", __PRETTY_FUNCTION__, gai_strerror(status));
mbus_error_str_set(error_str);
return -1;
}

s.sin_family = AF_INET;
s.sin_port = htons(port);

/* resolve hostname */
if ((host_addr = gethostbyname(host)) == NULL)
// loop through all the results and connect to the first we can
for (p = servinfo; p != NULL; p = p->ai_next)
{
snprintf(error_str, sizeof(error_str), "%s: unknown host: %s", __PRETTY_FUNCTION__, host);
mbus_error_str_set(error_str);
return -1;
if ((handle->fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
{
continue;
}

if (connect(handle->fd, p->ai_addr, p->ai_addrlen) == -1)
{
close(handle->fd);
continue;
}

break; // if we get here, we must have connected successfully
}

memcpy((void *)(&s.sin_addr), (void *)(host_addr->h_addr), host_addr->h_length);
// Free addr info, we do not need it anymore
freeaddrinfo(servinfo);

if (connect(handle->fd, (struct sockaddr *)&s, sizeof(s)) < 0)
if (p == NULL)
{
snprintf(error_str, sizeof(error_str), "%s: Failed to establish connection to %s:%d", __PRETTY_FUNCTION__, host, port);
snprintf(error_str, sizeof(error_str), "%s: Failed to establish connection to %s:%s", __PRETTY_FUNCTION__, host, port);
mbus_error_str_set(error_str);
return -1;
}
Expand Down

0 comments on commit 827241a

Please sign in to comment.