This is an automated email from Gerrit. "zapb <[email protected]>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/9655
-- gerrit commit 82f112398ef113a4f7042100f078be11bfc02690 Author: Marc Schink <[email protected]> Date: Wed May 13 03:15:49 2026 +0200 adapter/jtag-vpi: Use getaddrinfo() to support hostnames and IPv6 Connection establishment currently supports only IPv4 addresses via inet_addr(). Replace inet_addr() with getaddrinfo() to allow using hostnames and to add IPv6 support. Change-Id: Ieca79b71c24df1cbb82e5fc27d19cf2566efb7f5 Signed-off-by: Marc Schink <[email protected]> diff --git a/doc/openocd.texi b/doc/openocd.texi index a7ea2898eb..6ecd0246c1 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -3704,7 +3704,7 @@ Specifies the TCP/IP address of the SystemVerilog DPI server interface. A JTAG driver acting as a client for the JTAG VPI server interface. @deffn {Config Command} {jtag_vpi set_address} address -Specifies the TCP/IP address of the JTAG VPI server. +Specifies the hostname or IP address of the JTAG VPI server. @end deffn @deffn {Config Command} {jtag_vpi set_port} port diff --git a/src/jtag/drivers/jtag_vpi.c b/src/jtag/drivers/jtag_vpi.c index fac27b3060..d2bb2ffe30 100644 --- a/src/jtag/drivers/jtag_vpi.c +++ b/src/jtag/drivers/jtag_vpi.c @@ -14,6 +14,9 @@ #endif #include <jtag/interface.h> +#ifdef HAVE_NETDB_H +#include <netdb.h> +#endif #ifdef HAVE_ARPA_INET_H #include <arpa/inet.h> #endif @@ -39,14 +42,13 @@ #define CMD_STOP_SIMU 4 /* jtag_vpi server port and address to connect to */ -static int server_port = DEFAULT_SERVER_PORT; +static uint16_t server_port = DEFAULT_SERVER_PORT; static char *server_address; /* Send CMD_STOP_SIMU to server when OpenOCD exits? */ static bool stop_sim_on_exit; static int sockfd; -static struct sockaddr_in serv_addr; /* One jtag_vpi "packet" as sent over a TCP channel. */ struct vpi_cmd { @@ -524,43 +526,68 @@ static int jtag_vpi_execute_queue(struct jtag_command *cmd_queue) static int jtag_vpi_init(void) { - int flag = 1; + if (!server_address) + server_address = strdup(DEFAULT_SERVER_ADDRESS); + + const struct addrinfo hints = { + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM + }; + + char port_str[5 + 1]; + snprintf(port_str, sizeof(port_str), "%" PRIu16, server_port); - sockfd = socket(AF_INET, SOCK_STREAM, 0); - if (sockfd < 0) { - LOG_ERROR("jtag_vpi: Could not create client socket"); + struct addrinfo *result; + int ret = getaddrinfo(server_address, port_str, &hints, &result); + + if (ret != 0) { + LOG_ERROR("getaddrinfo: %s", gai_strerror(ret)); return ERROR_FAIL; } - memset(&serv_addr, 0, sizeof(serv_addr)); - - serv_addr.sin_family = AF_INET; - serv_addr.sin_port = htons(server_port); + struct addrinfo *rp; + for (rp = result; rp ; rp = rp->ai_next) { + sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if (sockfd == -1) + continue; - if (!server_address) - server_address = strdup(DEFAULT_SERVER_ADDRESS); + if (connect(sockfd, rp->ai_addr, rp->ai_addrlen) != -1) + break; - serv_addr.sin_addr.s_addr = inet_addr(server_address); + close(sockfd); + } - if (serv_addr.sin_addr.s_addr == INADDR_NONE) { - LOG_ERROR("jtag_vpi: inet_addr error occurred"); + if (!rp) { + LOG_ERROR("jtag_vpi: Can't connect to %s : %" PRIu16, + server_address, server_port); + freeaddrinfo(result); return ERROR_FAIL; } - if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { - close(sockfd); - LOG_ERROR("jtag_vpi: Can't connect to %s : %u", server_address, server_port); - return ERROR_COMMAND_CLOSE_CONNECTION; + bool is_loopback = false; + if (rp->ai_family == AF_INET) { + const struct sockaddr_in *sa = (const struct sockaddr_in *)rp->ai_addr; + is_loopback = (sa->sin_addr.s_addr == htonl(INADDR_LOOPBACK)); + } else if (rp->ai_family == AF_INET6) { + const struct sockaddr_in6 *sa = (const struct sockaddr_in6 *)rp->ai_addr; + is_loopback = IN6_IS_ADDR_LOOPBACK(&sa->sin6_addr); } - if (serv_addr.sin_addr.s_addr == htonl(INADDR_LOOPBACK)) { + if (is_loopback) { /* This increases performance dramatically for local - * connections, which is the most likely arrangement - * for a VPI connection. */ - setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int)); + * connections, which is the most likely arrangement + * for a VPI connection. */ + LOG_DEBUG("Enabling TCP_NODELAY to enhance the speed of local connections"); + + int flag = 1; + setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, + sizeof(int)); } - LOG_INFO("jtag_vpi: Connection to %s : %u successful", server_address, server_port); + freeaddrinfo(result); + + LOG_INFO("jtag_vpi: Connection to %s : %" PRIu16 " successful", + server_address, server_port); return ERROR_OK; } @@ -594,8 +621,8 @@ COMMAND_HANDLER(jtag_vpi_set_port) if (CMD_ARGC == 0) return ERROR_COMMAND_SYNTAX_ERROR; - COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], server_port); - LOG_INFO("jtag_vpi: server port set to %u", server_port); + COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], server_port); + LOG_INFO("jtag_vpi: server port set to %" PRIu16, server_port); return ERROR_OK; } @@ -634,7 +661,7 @@ static const struct command_registration jtag_vpi_subcommand_handlers[] = { .name = "set_address", .handler = &jtag_vpi_set_address, .mode = COMMAND_CONFIG, - .help = "set the IP address of the jtag_vpi server (default: 127.0.0.1)", + .help = "set the hostname or IP address of the jtag_vpi server (default: 127.0.0.1)", .usage = "ipv4_addr", }, { --
