20 #include <freerdp/config.h>
28 #include <winpr/crt.h>
29 #include <winpr/windows.h>
30 #include <freerdp/log.h>
36 #include <sys/ioctl.h>
37 #include <sys/socket.h>
38 #include <arpa/inet.h>
39 #include <netinet/in.h>
43 #if defined(HAVE_AF_VSOCK_H)
45 #include <linux/vm_sockets.h>
48 #include <winpr/handle.h>
53 #define TAG FREERDP_TAG("core.listener")
55 static BOOL freerdp_listener_open_from_vsock(freerdp_listener* instance,
const char* bind_address,
58 #if defined(HAVE_AF_VSOCK_H)
59 rdpListener* listener = (rdpListener*)instance->listener;
60 const int sockfd = socket(AF_VSOCK, SOCK_STREAM, 0);
63 char ebuffer[256] = { 0 };
64 WLog_ERR(TAG,
"Error creating socket: %s", winpr_strerror(errno, ebuffer,
sizeof(ebuffer)));
67 const int flags = fcntl(sockfd, F_GETFL, 0);
68 if (fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) == -1)
70 char ebuffer[256] = { 0 };
71 WLog_ERR(TAG,
"Error making socket nonblocking: %s",
72 winpr_strerror(errno, ebuffer,
sizeof(ebuffer)));
73 closesocket((SOCKET)sockfd);
76 struct sockaddr_vm addr = { 0 };
78 addr.svm_family = AF_VSOCK;
83 unsigned long val = strtoul(bind_address, &ptr, 10);
84 if (errno || (val > UINT32_MAX))
86 char ebuffer[256] = { 0 };
87 WLog_ERR(TAG,
"could not extract port from '%s', value=%ul, error=%s", bind_address, val,
88 winpr_strerror(errno, ebuffer,
sizeof(ebuffer)));
92 if (bind(sockfd, (
struct sockaddr*)&addr,
sizeof(
struct sockaddr_vm)) == -1)
94 char ebuffer[256] = { 0 };
95 WLog_ERR(TAG,
"Error binding vsock at cid %d port %d: %s", addr.svm_cid, port,
96 winpr_strerror(errno, ebuffer,
sizeof(ebuffer)));
97 closesocket((SOCKET)sockfd);
101 if (listen(sockfd, 10) == -1)
103 char ebuffer[256] = { 0 };
104 WLog_ERR(TAG,
"Error listening to socket at cid %d port %d: %s", addr.svm_cid, port,
105 winpr_strerror(errno, ebuffer,
sizeof(ebuffer)));
106 closesocket((SOCKET)sockfd);
109 listener->sockfds[listener->num_sockfds] = sockfd;
110 listener->events[listener->num_sockfds] = WSACreateEvent();
112 if (!listener->events[listener->num_sockfds])
114 listener->num_sockfds = 0;
117 WSAEventSelect(sockfd, listener->events[listener->num_sockfds], FD_READ | FD_ACCEPT | FD_CLOSE);
118 listener->num_sockfds++;
120 WLog_INFO(TAG,
"Listening on %s:%d", bind_address, port);
123 WLog_ERR(TAG,
"compiled without AF_VSOCK, '%s' not supported", bind_address);
128 static BOOL freerdp_listener_open(freerdp_listener* instance,
const char* bind_address, UINT16 port)
134 void* sin_addr = NULL;
135 int option_value = 0;
136 struct addrinfo* res = NULL;
137 rdpListener* listener = (rdpListener*)instance->listener;
143 ai_flags = AI_PASSIVE;
145 if (utils_is_vsock(bind_address))
147 bind_address = utils_is_vsock(bind_address);
148 return freerdp_listener_open_from_vsock(instance, bind_address, port);
151 res = freerdp_tcp_resolve_host(bind_address, port, ai_flags);
156 for (
struct addrinfo* ai = res; ai && (listener->num_sockfds < 5); ai = ai->ai_next)
158 if ((ai->ai_family != AF_INET) && (ai->ai_family != AF_INET6))
161 if (listener->num_sockfds == MAX_LISTENER_HANDLES)
163 WLog_ERR(TAG,
"too many listening sockets");
167 sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
171 WLog_ERR(TAG,
"socket");
177 if (ai->ai_family == AF_INET)
178 sin_addr = &(((
struct sockaddr_in*)ai->ai_addr)->sin_addr);
181 sin_addr = &(((
struct sockaddr_in6*)ai->ai_addr)->sin6_addr);
182 if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (
void*)&option_value,
183 sizeof(option_value)) == -1)
184 WLog_ERR(TAG,
"setsockopt");
187 inet_ntop(ai->ai_family, sin_addr, addr,
sizeof(addr));
189 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (
void*)&option_value,
190 sizeof(option_value)) == -1)
191 WLog_ERR(TAG,
"setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR)");
194 if (fcntl(sockfd, F_SETFL, O_NONBLOCK) != 0)
195 WLog_ERR(TAG,
"fcntl(sockfd, F_SETFL, O_NONBLOCK)");
198 ioctlsocket(sockfd, FIONBIO, &arg);
200 status = _bind((SOCKET)sockfd, ai->ai_addr, ai->ai_addrlen);
204 closesocket((SOCKET)sockfd);
208 status = _listen((SOCKET)sockfd, 10);
212 WLog_ERR(TAG,
"listen");
213 closesocket((SOCKET)sockfd);
218 listener->sockfds[listener->num_sockfds] = sockfd;
219 listener->events[listener->num_sockfds] = WSACreateEvent();
221 if (!listener->events[listener->num_sockfds])
223 listener->num_sockfds = 0;
227 WSAEventSelect(sockfd, listener->events[listener->num_sockfds],
228 FD_READ | FD_ACCEPT | FD_CLOSE);
229 listener->num_sockfds++;
230 WLog_INFO(TAG,
"Listening on [%s]:%" PRIu16, addr, port);
234 return (listener->num_sockfds > 0 ? TRUE : FALSE);
237 static BOOL freerdp_listener_open_local(freerdp_listener* instance,
const char* path)
242 struct sockaddr_un addr = { 0 };
243 rdpListener* listener = (rdpListener*)instance->listener;
244 HANDLE hevent = NULL;
246 if (listener->num_sockfds == MAX_LISTENER_HANDLES)
248 WLog_ERR(TAG,
"too many listening sockets");
252 sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
256 WLog_ERR(TAG,
"socket");
260 int rc = fcntl(sockfd, F_SETFL, O_NONBLOCK);
263 WLog_ERR(TAG,
"fcntl(sockfd, F_SETFL, O_NONBLOCK)");
264 closesocket((SOCKET)sockfd);
268 addr.sun_family = AF_UNIX;
269 strncpy(addr.sun_path, path,
sizeof(addr.sun_path) - 1);
271 status = _bind(sockfd, (
struct sockaddr*)&addr,
sizeof(addr));
275 WLog_ERR(TAG,
"bind");
276 closesocket((SOCKET)sockfd);
280 status = _listen(sockfd, 10);
284 WLog_ERR(TAG,
"listen");
285 closesocket((SOCKET)sockfd);
289 hevent = CreateFileDescriptorEvent(NULL, FALSE, FALSE, sockfd, WINPR_FD_READ);
293 WLog_ERR(TAG,
"failed to create sockfd event");
294 closesocket((SOCKET)sockfd);
298 listener->sockfds[listener->num_sockfds] = sockfd;
299 listener->events[listener->num_sockfds] = hevent;
300 listener->num_sockfds++;
301 WLog_INFO(TAG,
"Listening on socket %s.", addr.sun_path);
308 static BOOL freerdp_listener_open_from_socket(freerdp_listener* instance,
int fd)
311 rdpListener* listener = (rdpListener*)instance->listener;
313 if (listener->num_sockfds == MAX_LISTENER_HANDLES)
315 WLog_ERR(TAG,
"too many listening sockets");
319 if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
322 listener->sockfds[listener->num_sockfds] = fd;
323 listener->events[listener->num_sockfds] = WSACreateEvent();
325 if (!listener->events[listener->num_sockfds])
328 WSAEventSelect(fd, listener->events[listener->num_sockfds], FD_READ | FD_ACCEPT | FD_CLOSE);
330 listener->num_sockfds++;
331 WLog_INFO(TAG,
"Listening on socket %d.", fd);
338 static void freerdp_listener_close(freerdp_listener* instance)
340 rdpListener* listener = (rdpListener*)instance->listener;
342 for (
int i = 0; i < listener->num_sockfds; i++)
344 closesocket((SOCKET)listener->sockfds[i]);
345 (void)CloseHandle(listener->events[i]);
348 listener->num_sockfds = 0;
351 #if defined(WITH_FREERDP_DEPRECATED)
352 static BOOL freerdp_listener_get_fds(freerdp_listener* instance,
void** rfds,
int* rcount)
354 rdpListener* listener = (rdpListener*)instance->listener;
356 if (listener->num_sockfds < 1)
359 for (
int index = 0; index < listener->num_sockfds; index++)
361 rfds[*rcount] = (
void*)(
long)(listener->sockfds[index]);
369 static DWORD freerdp_listener_get_event_handles(freerdp_listener* instance, HANDLE* events,
372 rdpListener* listener = (rdpListener*)instance->listener;
374 if (listener->num_sockfds < 1)
377 if (listener->num_sockfds > (INT64)nCount)
380 for (
int index = 0; index < listener->num_sockfds; index++)
382 events[index] = listener->events[index];
385 return listener->num_sockfds;
388 BOOL freerdp_peer_set_local_and_hostname(freerdp_peer* client,
389 const struct sockaddr_storage* peer_addr)
391 const void* sin_addr = NULL;
392 const BYTE localhost6_bytes[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
394 WINPR_ASSERT(client);
395 WINPR_ASSERT(peer_addr);
397 if (peer_addr->ss_family == AF_INET)
399 const UINT32* usin_addr = sin_addr = &(((
const struct sockaddr_in*)peer_addr)->sin_addr);
401 if ((*usin_addr) == 0x0100007f)
402 client->local = TRUE;
404 else if (peer_addr->ss_family == AF_INET6)
406 const struct sockaddr_in6* usin_addr = sin_addr =
407 &(((
const struct sockaddr_in6*)peer_addr)->sin6_addr);
409 if (memcmp(usin_addr, localhost6_bytes, 16) == 0)
410 client->local = TRUE;
414 #if defined(HAVE_AF_VSOCK_H)
415 else if (peer_addr->ss_family == AF_UNIX || peer_addr->ss_family == AF_VSOCK)
417 else if (peer_addr->ss_family == AF_UNIX)
419 client->local = TRUE;
423 WLog_INFO(TAG,
"Accepting client from localhost");
426 inet_ntop(peer_addr->ss_family, sin_addr, client->hostname,
sizeof(client->hostname));
431 static BOOL freerdp_check_and_create_client(freerdp_listener* instance,
int peer_sockfd,
432 const struct sockaddr_storage* peer_addr)
434 WINPR_ASSERT(instance);
435 WINPR_ASSERT(peer_sockfd >= 0);
436 WINPR_ASSERT(peer_addr);
438 const BOOL check = IFCALLRESULT(TRUE, instance->CheckPeerAcceptRestrictions, instance);
441 closesocket((SOCKET)peer_sockfd);
445 freerdp_peer* client = freerdp_peer_new(peer_sockfd);
448 closesocket((SOCKET)peer_sockfd);
452 if (!freerdp_peer_set_local_and_hostname(client, peer_addr))
454 freerdp_peer_free(client);
458 const BOOL peer_accepted = IFCALLRESULT(FALSE, instance->PeerAccepted, instance, client);
461 WLog_ERR(TAG,
"PeerAccepted callback failed");
462 freerdp_peer_free(client);
468 static BOOL freerdp_listener_check_fds(freerdp_listener* instance)
470 rdpListener* listener = (rdpListener*)instance->listener;
472 if (listener->num_sockfds < 1)
475 for (
int i = 0; i < listener->num_sockfds; i++)
477 struct sockaddr_storage peer_addr = { 0 };
479 (void)WSAResetEvent(listener->events[i]);
480 int peer_addr_size =
sizeof(peer_addr);
482 _accept(listener->sockfds[i], (
struct sockaddr*)&peer_addr, &peer_addr_size);
484 if (peer_sockfd == (SOCKET)-1)
486 char buffer[128] = { 0 };
488 int wsa_error = WSAGetLastError();
491 if (wsa_error == WSAEWOULDBLOCK)
496 if (errno == EAGAIN || errno == EWOULDBLOCK)
500 WLog_WARN(TAG,
"accept failed with %s", winpr_strerror(errno, buffer,
sizeof(buffer)));
504 if (!freerdp_check_and_create_client(instance, (
int)peer_sockfd, &peer_addr))
511 freerdp_listener* freerdp_listener_new(
void)
513 freerdp_listener* instance = NULL;
514 rdpListener* listener = NULL;
515 instance = (freerdp_listener*)calloc(1,
sizeof(freerdp_listener));
520 instance->Open = freerdp_listener_open;
521 instance->OpenLocal = freerdp_listener_open_local;
522 instance->OpenFromSocket = freerdp_listener_open_from_socket;
523 #if defined(WITH_FREERDP_DEPRECATED)
524 instance->GetFileDescriptor = freerdp_listener_get_fds;
526 instance->GetEventHandles = freerdp_listener_get_event_handles;
527 instance->CheckFileDescriptor = freerdp_listener_check_fds;
528 instance->Close = freerdp_listener_close;
529 listener = (rdpListener*)calloc(1,
sizeof(rdpListener));
537 listener->instance = instance;
538 instance->listener = (
void*)listener;
542 void freerdp_listener_free(freerdp_listener* instance)
546 free(instance->listener);