diff --git a/common/os_calls.c b/common/os_calls.c index e7fc144c..6289c276 100644 --- a/common/os_calls.c +++ b/common/os_calls.c @@ -3823,3 +3823,132 @@ g_mirror_memcpy(void *dst, const void *src, int len) return 0; } +/*****************************************************************************/ +int +g_tcp4_socket(void) +{ +#if defined(XRDP_ENABLE_IPV6ONLY) + return -1; +#else + int rv; + int option_value; + socklen_t option_len; + + rv = socket(AF_INET, SOCK_STREAM, 0); + if (rv < 0) + { + return -1; + } + option_len = sizeof(option_value); + if (getsockopt(rv, SOL_SOCKET, SO_REUSEADDR, + (char *) &option_value, &option_len) == 0) + { + if (option_value == 0) + { + option_value = 1; + option_len = sizeof(option_value); + if (setsockopt(rv, SOL_SOCKET, SO_REUSEADDR, + (char *) &option_value, option_len) < 0) + { + } + } + } + return rv; +#endif +} + +/*****************************************************************************/ +int +g_tcp4_bind(int sck, const char *port, const char *address) +{ +#if defined(XRDP_ENABLE_IPV6ONLY) + return -1; +#else + struct sockaddr_in s; + + memset(&s, 0, sizeof(s)); + s.sin_family = AF_INET; + s.sin_addr.s_addr = htonl(INADDR_ANY); + s.sin_port = htons((uint16_t) atoi(port)); + if (bind(sck, (struct sockaddr*) &s, sizeof(s)) == 0) + { + return 0; + } + return -1; +#endif +} + +/*****************************************************************************/ +int +g_tcp6_socket(void) +{ +#if defined(XRDP_ENABLE_IPV6) + int rv; + int option_value; + socklen_t option_len; + + rv = socket(AF_INET6, SOCK_STREAM, 0); + if (rv < 0) + { + return -1; + } + option_len = sizeof(option_value); + if (getsockopt(rv, IPPROTO_IPV6, IPV6_V6ONLY, + (char *) &option_value, &option_len) == 0) + { +#if defined(XRDP_ENABLE_IPV6ONLY) + if (option_value == 0) + { + option_value = 1; +#else + if (option_value != 0) + { + option_value = 0; +#endif + option_len = sizeof(option_value); + if (setsockopt(rv, IPPROTO_IPV6, IPV6_V6ONLY, + (char *) &option_value, option_len) < 0) + { + } + } + } + option_len = sizeof(option_value); + if (getsockopt(rv, SOL_SOCKET, SO_REUSEADDR, + (char *) &option_value, &option_len) == 0) + { + if (option_value == 0) + { + option_value = 1; + option_len = sizeof(option_value); + if (setsockopt(rv, SOL_SOCKET, SO_REUSEADDR, + (char *) &option_value, option_len) < 0) + { + } + } + } + return rv; +#else + return -1; +#endif +} + +/*****************************************************************************/ +int +g_tcp6_bind(int sck, const char *port, const char *address) +{ +#if defined(XRDP_ENABLE_IPV6) + struct sockaddr_in6 sa; + + memset(&sa, 0, sizeof(sa)); + sa.sin6_family = AF_INET6; + sa.sin6_addr = in6addr_any; + sa.sin6_port = htons((uint16_t) atoi(port)); + if (bind(sck, (struct sockaddr *) &sa, sizeof(sa)) == 0) + { + return 0; + } + return -1; +#else + return -1; +#endif +} diff --git a/common/os_calls.h b/common/os_calls.h index e42e95bd..6cbe499a 100644 --- a/common/os_calls.h +++ b/common/os_calls.h @@ -183,6 +183,10 @@ void * g_shmat(int shmid); int g_shmdt(const void *shmaddr); int g_gethostname(char *name, int len); int g_mirror_memcpy(void *dst, const void *src, int len); +int g_tcp4_socket(void); +int g_tcp4_bind(int sck, const char *port, const char *address); +int g_tcp6_socket(void); +int g_tcp6_bind(int sck, const char *port, const char *address); /* glib-style wrappers */ #define g_new(struct_type, n_structs) \ diff --git a/common/trans.c b/common/trans.c index 0882d643..608b8819 100644 --- a/common/trans.c +++ b/common/trans.c @@ -885,7 +885,42 @@ trans_listen_address(struct trans *self, char *port, const char *address) } } } - + else if (self->mode == TRANS_MODE_TCP4) /* tcp4 */ + { + self->sck = g_tcp4_socket(); + if (self->sck < 0) + { + return 1; + } + g_tcp_set_non_blocking(self->sck); + if (g_tcp4_bind(self->sck, port, address) == 0) + { + if (g_tcp_listen(self->sck) == 0) + { + self->status = TRANS_STATUS_UP; /* ok */ + self->type1 = TRANS_TYPE_LISTENER; /* listener */ + return 0; + } + } + } + else if (self->mode == TRANS_MODE_TCP6) /* tcp6 */ + { + self->sck = g_tcp6_socket(); + if (self->sck < 0) + { + return 1; + } + g_tcp_set_non_blocking(self->sck); + if (g_tcp6_bind(self->sck, port, address) == 0) + { + if (g_tcp_listen(self->sck) == 0) + { + self->status = TRANS_STATUS_UP; /* ok */ + self->type1 = TRANS_TYPE_LISTENER; /* listener */ + return 0; + } + } + } return 1; } diff --git a/common/trans.h b/common/trans.h index 30559347..1e1efd16 100644 --- a/common/trans.h +++ b/common/trans.h @@ -24,9 +24,11 @@ #include "arch.h" #include "parse.h" -#define TRANS_MODE_TCP 1 +#define TRANS_MODE_TCP 1 /* tcp6 if defined, else tcp4 */ #define TRANS_MODE_UNIX 2 #define TRANS_MODE_VSOCK 3 +#define TRANS_MODE_TCP4 4 /* tcp4 only */ +#define TRANS_MODE_TCP6 6 /* tcp6 only */ #define TRANS_TYPE_LISTENER 1 #define TRANS_TYPE_SERVER 2 diff --git a/xrdp/xrdp_listen.c b/xrdp/xrdp_listen.c index b484ff09..1ce84a7d 100644 --- a/xrdp/xrdp_listen.c +++ b/xrdp/xrdp_listen.c @@ -470,7 +470,7 @@ xrdp_listen_pp(struct xrdp_listen *self, int *index, bytes = xrdp_listen_parse_integer(port, 128, str, str_end - str); str += bytes; lindex += bytes; - *mode = TRANS_MODE_TCP; + *mode = TRANS_MODE_TCP4; *index = lindex; return 0; } @@ -482,7 +482,7 @@ xrdp_listen_pp(struct xrdp_listen *self, int *index, bytes = xrdp_listen_parse_integer(port, 128, str, str_end - str); str += bytes; lindex += bytes; - *mode = TRANS_MODE_TCP; + *mode = TRANS_MODE_TCP4; *index = lindex; return 0; } @@ -496,7 +496,7 @@ xrdp_listen_pp(struct xrdp_listen *self, int *index, bytes = xrdp_listen_parse_integer(port, 128, str, str_end - str); str += bytes; lindex += bytes; - *mode = TRANS_MODE_TCP; + *mode = TRANS_MODE_TCP4; *index = lindex; return 0; } @@ -508,7 +508,7 @@ xrdp_listen_pp(struct xrdp_listen *self, int *index, bytes = xrdp_listen_parse_integer(port, 128, str, str_end - str); str += bytes; lindex += bytes; - *mode = TRANS_MODE_TCP; + *mode = TRANS_MODE_TCP6; *index = lindex; return 0; } @@ -520,7 +520,7 @@ xrdp_listen_pp(struct xrdp_listen *self, int *index, bytes = xrdp_listen_parse_integer(port, 128, str, str_end - str); str += bytes; lindex += bytes; - *mode = TRANS_MODE_TCP; + *mode = TRANS_MODE_TCP6; *index = lindex; return 0; } @@ -534,7 +534,7 @@ xrdp_listen_pp(struct xrdp_listen *self, int *index, bytes = xrdp_listen_parse_integer(port, 128, str, str_end - str); str += bytes; lindex += bytes; - *mode = TRANS_MODE_TCP; + *mode = TRANS_MODE_TCP6; *index = lindex; return 0; }