Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -6444,6 +6444,14 @@ then :

fi

ac_fn_c_check_header_compile "$LINENO" "linux/vm_sockets.h" "ac_cv_header_linux_vm_sockets_h" "#include <sys/socket.h>
"
if test "x$ac_cv_header_linux_vm_sockets_h" = xyes
then :
printf "%s\n" "#define HAVE_LINUX_VM_SOCKETS_H 1" >>confdefs.h

fi


# Checks for typedefs, structures, and compiler characteristics.
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5
Expand Down
1 change: 1 addition & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,7 @@ AC_CHECK_HEADERS([netinet/in.h netinet/tcp.h \
utmpx.h lastlog.h paths.h util.h netdb.h security/pam_appl.h \
pam/pam_appl.h netinet/in_systm.h sys/uio.h linux/pkt_sched.h \
sys/random.h sys/prctl.h])
AC_CHECK_HEADERS([linux/vm_sockets.h], , , [#include <sys/socket.h>])

# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
Expand Down
3 changes: 3 additions & 0 deletions src/config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,9 @@
/* Define to 1 if you have the <linux/pkt_sched.h> header file. */
#undef HAVE_LINUX_PKT_SCHED_H

/* Define to 1 if you have the <linux/vm_sockets.h> header file. */
#undef HAVE_LINUX_VM_SOCKETS_H

/* Have login() function */
#undef HAVE_LOGIN

Expand Down
4 changes: 4 additions & 0 deletions src/includes.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,10 @@ typedef u_int32_t uint32_t;
#include <linux/pkt_sched.h>
#endif

#ifdef HAVE_LINUX_VM_SOCKETS_H
#include <linux/vm_sockets.h>
#endif

#if DROPBEAR_PLUGIN
#include <dlfcn.h>
#endif
Expand Down
106 changes: 95 additions & 11 deletions src/netio.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,63 @@
#include "debug.h"
#include "runopts.h"

#ifdef HAVE_LINUX_VM_SOCKETS_H
void
dropbear_freeaddrinfo(struct addrinfo *ai)
{
struct addrinfo *next;

/* For AF_VSOCK, we allocated it ourselves, so free it here as we
* cannot be sure that the stock freeaddrinfo free's it in the same
* way as we allocated it.
*/
if (ai && ai->ai_family != AF_VSOCK)
return freeaddrinfo(ai);
Comment on lines +18 to +19
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All if statements need braces


for(; ai != NULL;) {
next = ai->ai_next;
free(ai);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

m_free

ai = next;
}
}

int dropbear_getaddrinfo(const char *hostname, const char *servname,
const struct addrinfo *hints, struct addrinfo **res)
{
const char *vsock = strstr(hostname, "%vsock");
if (vsock && (hints->ai_family == AF_UNSPEC || hints->ai_family == AF_VSOCK)) {
struct addrinfo *vsock_res;
struct sockaddr_vm *vsockaddr;

vsock_res = calloc(1, sizeof(struct addrinfo) + sizeof(*vsockaddr));
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

m_calloc

vsockaddr = (void *)(vsock_res + 1);
vsock_res->ai_family = AF_VSOCK;
vsock_res->ai_socktype = hints->ai_socktype;
vsock_res->ai_addr = (struct sockaddr *)vsockaddr;
vsock_res->ai_addrlen = sizeof(*vsockaddr);
vsockaddr->svm_family = AF_VSOCK;
if (vsock != hostname)
vsockaddr->svm_cid = atoi(hostname);
Copy link
Owner

@mkj mkj Sep 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use m_str_to_uint instead of atoi, that has error checking. Though that won't deal with splitting the string.

else
vsockaddr->svm_cid = VMADDR_CID_ANY;
vsockaddr->svm_port = atoi(servname);

if (res)
*res = vsock_res;
else
dropbear_freeaddrinfo(vsock_res);

return 0;
}

return getaddrinfo(hostname, servname, hints, res);
}
#else
#define dropbear_freeaddrinfo freeaddrinfo
#define dropbear_getaddrinfo getaddrinfo
#endif


struct dropbear_progress_connection {
struct addrinfo *res;
struct addrinfo *res_iter;
Expand Down Expand Up @@ -92,7 +149,7 @@ static void connect_try_next(struct dropbear_progress_connection *c) {
hints.ai_family = r->ai_family;
hints.ai_flags = AI_PASSIVE;

err = getaddrinfo(c->bind_address, c->bind_port, &hints, &bindaddr);
err = dropbear_getaddrinfo(c->bind_address, c->bind_port, &hints, &bindaddr);
if (err) {
int len = 100 + strlen(gai_strerror(err));
m_free(c->errstring);
Expand Down Expand Up @@ -127,7 +184,8 @@ static void connect_try_next(struct dropbear_progress_connection *c) {
setnonblocking(c->sock);

#if DROPBEAR_CLIENT_TCP_FAST_OPEN
fastopen = (c->writequeue != NULL && r->ai_family != AF_UNIX);
fastopen = (c->writequeue != NULL &&
(r->ai_family == AF_INET || r->ai_family == AF_INET6);

if (fastopen) {
memset(&message, 0x0, sizeof(message));
Expand Down Expand Up @@ -214,7 +272,7 @@ struct dropbear_progress_connection *connect_remote(const char* remotehost, cons
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = AF_UNSPEC;

err = getaddrinfo(remotehost, remoteport, &hints, &c->res);
err = dropbear_getaddrinfo(remotehost, remoteport, &hints, &c->res);
if (err) {
int len;
len = 100 + strlen(gai_strerror(err));
Expand Down Expand Up @@ -507,6 +565,11 @@ int get_sock_port(int sock) {
return 0;
}

#ifdef HAVE_LINUX_VM_SOCKETS_H
if (from.ss_family == AF_VSOCK)
return ((struct sockaddr_vm *)&from)->svm_port;
#endif

/* Work around Linux IPv6 weirdness */
if (from.ss_family == AF_INET6)
fromlen = sizeof(struct sockaddr_in6);
Expand Down Expand Up @@ -537,7 +600,6 @@ int dropbear_listen(const char* address, const char* port,
unsigned int nsock;
int val;
int sock;
uint16_t *allocated_lport_p = NULL;
int allocated_lport = 0;

TRACE(("enter dropbear_listen"))
Expand Down Expand Up @@ -569,7 +631,8 @@ int dropbear_listen(const char* address, const char* port,
}
hints.ai_flags = AI_PASSIVE;
}
err = getaddrinfo(address, port, &hints, &res0);

err = dropbear_getaddrinfo(address, port, &hints, &res0);

if (err) {
if (errstring != NULL && *errstring == NULL) {
Expand All @@ -579,7 +642,7 @@ int dropbear_listen(const char* address, const char* port,
snprintf(*errstring, len, "Error resolving: %s", gai_strerror(err));
}
if (res0) {
freeaddrinfo(res0);
dropbear_freeaddrinfo(res0);
res0 = NULL;
}
TRACE(("leave dropbear_listen: failed resolving"))
Expand All @@ -597,11 +660,17 @@ int dropbear_listen(const char* address, const char* port,
res = res->ai_next) {
if (allocated_lport > 0) {
if (AF_INET == res->ai_family) {
allocated_lport_p = &((struct sockaddr_in *)res->ai_addr)->sin_port;
((struct sockaddr_in *)res->ai_addr)->sin_port =
htons(allocated_lport);
} else if (AF_INET6 == res->ai_family) {
allocated_lport_p = &((struct sockaddr_in6 *)res->ai_addr)->sin6_port;
((struct sockaddr_in6 *)res->ai_addr)->sin6_port =
htons(allocated_lport);
#ifdef HAVE_LINUX_VM_SOCKETS_H
} else if (AF_VSOCK == res->ai_family) {
((struct sockaddr_vm *)res->ai_addr)->svm_port =
allocated_lport;
#endif
}
*allocated_lport_p = htons(allocated_lport);
}

/* Get a socket */
Expand Down Expand Up @@ -659,7 +728,7 @@ int dropbear_listen(const char* address, const char* port,
}

if (res0) {
freeaddrinfo(res0);
dropbear_freeaddrinfo(res0);
res0 = NULL;
}

Expand Down Expand Up @@ -722,7 +791,22 @@ void getaddrstring(struct sockaddr_storage* addr,
#if !DO_HOST_LOOKUP
host_lookup = 0;
#endif


#ifdef HAVE_LINUX_VM_SOCKETS_H
if (addr->ss_family == AF_VSOCK) {
struct sockaddr_vm *vsockaddr = (void *)addr;

snprintf(host, NI_MAXHOST, "%u%%vsock", vsockaddr->svm_cid);
if (ret_host)
*ret_host = m_strdup(host);
snprintf(serv, NI_MAXSERV, "%u", vsockaddr->svm_port);
if (ret_port)
*ret_port = m_strdup(serv);

return;
}
#endif

if (host_lookup) {
flags = NI_NUMERICSERV;
}
Expand Down
3 changes: 3 additions & 0 deletions src/svr-tcpfwd.c
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,9 @@ static int newtcpdirect(struct Channel * channel) {
origport = buf_getint(ses.payload);

/* best be sure */
#ifdef HAVE_LINUX_VM_SOCKETS_H
if (strstr(orighost, "%vsock") != NULL) {} else
#endif
Comment on lines +289 to +291
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about doing string comparison on the hostname received from the peer here. Does https://libvirt.org/ssh-proxy.html use the same hostname format?

Can the #ifdef and if be done in a nicer way?

if (origport > 65535 || destport > 65535) {
TRACE(("leave newtcpdirect: port > 65535"))
goto out;
Expand Down
7 changes: 7 additions & 0 deletions src/tcp-accept.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@ static void tcp_acceptor(const struct Listener *listener, int sock) {
return;
}

#ifdef HAVE_LINUX_VM_SOCKETS_H
if (sa.ss_family == AF_VSOCK) {
struct sockaddr_vm *vsockaddr = (void *)&sa;
snprintf(ipstring, NI_MAXHOST - 1, "%u%%vsock", vsockaddr->svm_cid);
snprintf(portstring, NI_MAXSERV - 1, "%u", vsockaddr->svm_port);
Comment on lines +66 to +67
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

- 1 shouldn't be needed here?

} else
#endif
if (getnameinfo((struct sockaddr*)&sa, len, ipstring, sizeof(ipstring),
portstring, sizeof(portstring),
NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
Expand Down
Loading