Skip to content

Commit 714ed66

Browse files
committed
Permit use of AF_VSOCK using a %vsock hostname postfix
Optionally, one may give the CID to connect to or listen on before the %vsock. This works both for listening and connecting and also for "TCP" forwarding.
1 parent 1610699 commit 714ed66

File tree

7 files changed

+125
-15
lines changed

7 files changed

+125
-15
lines changed

configure

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6152,11 +6152,11 @@ if test x$ac_prog_cxx_stdcxx = xno
61526152
then :
61536153
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++11 features" >&5
61546154
printf %s "checking for $CXX option to enable C++11 features... " >&6; }
6155-
if test ${ac_cv_prog_cxx_11+y}
6155+
if test ${ac_cv_prog_cxx_cxx11+y}
61566156
then :
61576157
printf %s "(cached) " >&6
61586158
else $as_nop
6159-
ac_cv_prog_cxx_11=no
6159+
ac_cv_prog_cxx_cxx11=no
61606160
ac_save_CXX=$CXX
61616161
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
61626162
/* end confdefs.h. */
@@ -6198,11 +6198,11 @@ if test x$ac_prog_cxx_stdcxx = xno
61986198
then :
61996199
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++98 features" >&5
62006200
printf %s "checking for $CXX option to enable C++98 features... " >&6; }
6201-
if test ${ac_cv_prog_cxx_98+y}
6201+
if test ${ac_cv_prog_cxx_cxx98+y}
62026202
then :
62036203
printf %s "(cached) " >&6
62046204
else $as_nop
6205-
ac_cv_prog_cxx_98=no
6205+
ac_cv_prog_cxx_cxx98=no
62066206
ac_save_CXX=$CXX
62076207
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
62086208
/* end confdefs.h. */
@@ -6444,6 +6444,14 @@ then :
64446444

64456445
fi
64466446

6447+
ac_fn_c_check_header_compile "$LINENO" "linux/vm_sockets.h" "ac_cv_header_linux_vm_sockets_h" "#include <sys/socket.h>
6448+
"
6449+
if test "x$ac_cv_header_linux_vm_sockets_h" = xyes
6450+
then :
6451+
printf "%s\n" "#define HAVE_LINUX_VM_SOCKETS_H 1" >>confdefs.h
6452+
6453+
fi
6454+
64476455

64486456
# Checks for typedefs, structures, and compiler characteristics.
64496457
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5

configure.ac

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,7 @@ AC_CHECK_HEADERS([netinet/in.h netinet/tcp.h \
393393
utmpx.h lastlog.h paths.h util.h netdb.h security/pam_appl.h \
394394
pam/pam_appl.h netinet/in_systm.h sys/uio.h linux/pkt_sched.h \
395395
sys/random.h sys/prctl.h])
396+
AC_CHECK_HEADERS([linux/vm_sockets.h], , , [#include <sys/socket.h>])
396397

397398
# Checks for typedefs, structures, and compiler characteristics.
398399
AC_C_CONST

src/config.h.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,9 @@
174174
/* Define to 1 if you have the <linux/pkt_sched.h> header file. */
175175
#undef HAVE_LINUX_PKT_SCHED_H
176176

177+
/* Define to 1 if you have the <linux/vm_sockets.h> header file. */
178+
#undef HAVE_LINUX_VM_SOCKETS_H
179+
177180
/* Have login() function */
178181
#undef HAVE_LOGIN
179182

src/includes.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,10 @@ typedef u_int32_t uint32_t;
180180
#include <linux/pkt_sched.h>
181181
#endif
182182

183+
#ifdef HAVE_LINUX_VM_SOCKETS_H
184+
#include <linux/vm_sockets.h>
185+
#endif
186+
183187
#if DROPBEAR_PLUGIN
184188
#include <dlfcn.h>
185189
#endif

src/netio.c

Lines changed: 95 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,63 @@
55
#include "debug.h"
66
#include "runopts.h"
77

8+
#ifdef HAVE_LINUX_VM_SOCKETS_H
9+
void
10+
dropbear_freeaddrinfo(struct addrinfo *ai)
11+
{
12+
struct addrinfo *next;
13+
14+
/* For AF_VSOCK, we allocated it ourselves, so free it here as we
15+
* cannot be sure that the stock freeaddrinfo free's it in the same
16+
* way as we allocated it.
17+
*/
18+
if (ai && ai->ai_family != AF_VSOCK)
19+
return freeaddrinfo(ai);
20+
21+
for(; ai != NULL;) {
22+
next = ai->ai_next;
23+
free(ai);
24+
ai = next;
25+
}
26+
}
27+
28+
int dropbear_getaddrinfo(const char *hostname, const char *servname,
29+
const struct addrinfo *hints, struct addrinfo **res)
30+
{
31+
const char *vsock = strstr(hostname, "%vsock");
32+
if (vsock && (hints->ai_family == AF_UNSPEC || hints->ai_family == AF_VSOCK)) {
33+
struct addrinfo *vsock_res;
34+
struct sockaddr_vm *vsockaddr;
35+
36+
vsock_res = calloc(1, sizeof(struct addrinfo) + sizeof(*vsockaddr));
37+
vsockaddr = (void *)(vsock_res + 1);
38+
vsock_res->ai_family = AF_VSOCK;
39+
vsock_res->ai_socktype = hints->ai_socktype;
40+
vsock_res->ai_addr = (struct sockaddr *)vsockaddr;
41+
vsock_res->ai_addrlen = sizeof(*vsockaddr);
42+
vsockaddr->svm_family = AF_VSOCK;
43+
if (vsock != hostname)
44+
vsockaddr->svm_cid = atoi(hostname);
45+
else
46+
vsockaddr->svm_cid = VMADDR_CID_ANY;
47+
vsockaddr->svm_port = atoi(servname);
48+
49+
if (res)
50+
*res = vsock_res;
51+
else
52+
dropbear_freeaddrinfo(vsock_res);
53+
54+
return 0;
55+
}
56+
57+
return getaddrinfo(hostname, servname, hints, res);
58+
}
59+
#else
60+
#define dropbear_freeaddrinfo freeaddrinfo
61+
#define dropbear_getaddrinfo getaddrinfo
62+
#endif
63+
64+
865
struct dropbear_progress_connection {
966
struct addrinfo *res;
1067
struct addrinfo *res_iter;
@@ -92,7 +149,7 @@ static void connect_try_next(struct dropbear_progress_connection *c) {
92149
hints.ai_family = r->ai_family;
93150
hints.ai_flags = AI_PASSIVE;
94151

95-
err = getaddrinfo(c->bind_address, c->bind_port, &hints, &bindaddr);
152+
err = dropbear_getaddrinfo(c->bind_address, c->bind_port, &hints, &bindaddr);
96153
if (err) {
97154
int len = 100 + strlen(gai_strerror(err));
98155
m_free(c->errstring);
@@ -127,7 +184,8 @@ static void connect_try_next(struct dropbear_progress_connection *c) {
127184
setnonblocking(c->sock);
128185

129186
#if DROPBEAR_CLIENT_TCP_FAST_OPEN
130-
fastopen = (c->writequeue != NULL && r->ai_family != AF_UNIX);
187+
fastopen = (c->writequeue != NULL &&
188+
(r->ai_family == AF_INET || r->ai_family == AF_INET6);
131189

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

217-
err = getaddrinfo(remotehost, remoteport, &hints, &c->res);
275+
err = dropbear_getaddrinfo(remotehost, remoteport, &hints, &c->res);
218276
if (err) {
219277
int len;
220278
len = 100 + strlen(gai_strerror(err));
@@ -507,6 +565,11 @@ int get_sock_port(int sock) {
507565
return 0;
508566
}
509567

568+
#ifdef HAVE_LINUX_VM_SOCKETS_H
569+
if (from.ss_family == AF_VSOCK)
570+
return ((struct sockaddr_vm *)&from)->svm_port;
571+
#endif
572+
510573
/* Work around Linux IPv6 weirdness */
511574
if (from.ss_family == AF_INET6)
512575
fromlen = sizeof(struct sockaddr_in6);
@@ -537,7 +600,6 @@ int dropbear_listen(const char* address, const char* port,
537600
unsigned int nsock;
538601
int val;
539602
int sock;
540-
uint16_t *allocated_lport_p = NULL;
541603
int allocated_lport = 0;
542604

543605
TRACE(("enter dropbear_listen"))
@@ -569,7 +631,8 @@ int dropbear_listen(const char* address, const char* port,
569631
}
570632
hints.ai_flags = AI_PASSIVE;
571633
}
572-
err = getaddrinfo(address, port, &hints, &res0);
634+
635+
err = dropbear_getaddrinfo(address, port, &hints, &res0);
573636

574637
if (err) {
575638
if (errstring != NULL && *errstring == NULL) {
@@ -579,7 +642,7 @@ int dropbear_listen(const char* address, const char* port,
579642
snprintf(*errstring, len, "Error resolving: %s", gai_strerror(err));
580643
}
581644
if (res0) {
582-
freeaddrinfo(res0);
645+
dropbear_freeaddrinfo(res0);
583646
res0 = NULL;
584647
}
585648
TRACE(("leave dropbear_listen: failed resolving"))
@@ -597,11 +660,17 @@ int dropbear_listen(const char* address, const char* port,
597660
res = res->ai_next) {
598661
if (allocated_lport > 0) {
599662
if (AF_INET == res->ai_family) {
600-
allocated_lport_p = &((struct sockaddr_in *)res->ai_addr)->sin_port;
663+
((struct sockaddr_in *)res->ai_addr)->sin_port =
664+
htons(allocated_lport);
601665
} else if (AF_INET6 == res->ai_family) {
602-
allocated_lport_p = &((struct sockaddr_in6 *)res->ai_addr)->sin6_port;
666+
((struct sockaddr_in6 *)res->ai_addr)->sin6_port =
667+
htons(allocated_lport);
668+
#ifdef HAVE_LINUX_VM_SOCKETS_H
669+
} else if (AF_VSOCK == res->ai_family) {
670+
((struct sockaddr_vm *)res->ai_addr)->svm_port =
671+
allocated_lport;
672+
#endif
603673
}
604-
*allocated_lport_p = htons(allocated_lport);
605674
}
606675

607676
/* Get a socket */
@@ -659,7 +728,7 @@ int dropbear_listen(const char* address, const char* port,
659728
}
660729

661730
if (res0) {
662-
freeaddrinfo(res0);
731+
dropbear_freeaddrinfo(res0);
663732
res0 = NULL;
664733
}
665734

@@ -722,7 +791,22 @@ void getaddrstring(struct sockaddr_storage* addr,
722791
#if !DO_HOST_LOOKUP
723792
host_lookup = 0;
724793
#endif
725-
794+
795+
#ifdef HAVE_LINUX_VM_SOCKETS_H
796+
if (addr->ss_family == AF_VSOCK) {
797+
struct sockaddr_vm *vsockaddr = (void *)addr;
798+
799+
snprintf(host, NI_MAXHOST, "%u%%vsock", vsockaddr->svm_cid);
800+
if (ret_host)
801+
*ret_host = m_strdup(host);
802+
snprintf(serv, NI_MAXSERV, "%u", vsockaddr->svm_port);
803+
if (ret_port)
804+
*ret_port = m_strdup(serv);
805+
806+
return;
807+
}
808+
#endif
809+
726810
if (host_lookup) {
727811
flags = NI_NUMERICSERV;
728812
}

src/svr-tcpfwd.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,9 @@ static int newtcpdirect(struct Channel * channel) {
286286
origport = buf_getint(ses.payload);
287287

288288
/* best be sure */
289+
#ifdef HAVE_LINUX_VM_SOCKETS_H
290+
if (strstr(orighost, "%vsock") != NULL) {} else
291+
#endif
289292
if (origport > 65535 || destport > 65535) {
290293
TRACE(("leave newtcpdirect: port > 65535"))
291294
goto out;

src/tcp-accept.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@ static void tcp_acceptor(const struct Listener *listener, int sock) {
6060
return;
6161
}
6262

63+
#ifdef HAVE_LINUX_VM_SOCKETS_H
64+
if (sa.ss_family == AF_VSOCK) {
65+
struct sockaddr_vm *vsockaddr = (void *)&sa;
66+
snprintf(ipstring, NI_MAXHOST - 1, "%u%%vsock", vsockaddr->svm_cid);
67+
snprintf(portstring, NI_MAXSERV - 1, "%u", vsockaddr->svm_port);
68+
} else
69+
#endif
6370
if (getnameinfo((struct sockaddr*)&sa, len, ipstring, sizeof(ipstring),
6471
portstring, sizeof(portstring),
6572
NI_NUMERICHOST | NI_NUMERICSERV) != 0) {

0 commit comments

Comments
 (0)