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+
865struct 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 }
0 commit comments