summaryrefslogtreecommitdiff
path: root/src/core/socket_helpers.c
diff options
context:
space:
mode:
authorsss <sss@dark-alexandr.net>2023-01-17 00:38:19 +0300
committersss <sss@dark-alexandr.net>2023-01-17 00:38:19 +0300
commitcc3f33db7a8d3c4ad373e646b199808e01bc5d9b (patch)
treeec09d690c7656ab5f2cc72607e05fb359c24d8b2 /src/core/socket_helpers.c
added webrdp public code
Diffstat (limited to 'src/core/socket_helpers.c')
-rw-r--r--src/core/socket_helpers.c143
1 files changed, 143 insertions, 0 deletions
diff --git a/src/core/socket_helpers.c b/src/core/socket_helpers.c
new file mode 100644
index 0000000..2d2cdbb
--- /dev/null
+++ b/src/core/socket_helpers.c
@@ -0,0 +1,143 @@
+/* BSD-2-Clause license
+ *
+ * Copyright (c) 2018-2023 NST <www.newinfosec.ru>, sss <sss at dark-alexandr dot net>.
+ *
+ */
+
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <netinet/tcp.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+
+#include <stdbool.h>
+#include "webrdp_core_api.h"
+#include "log.h"
+
+void
+socket_make_non_block(int sock)
+{
+ int flags, r;
+ while ((flags = fcntl(sock, F_GETFL, 0)) == -1 && errno == EINTR)
+ {
+ }
+ if (flags == -1)
+ {
+ perror("fcntl");
+ exit(EXIT_FAILURE);
+ }
+ while ((r = fcntl(sock, F_SETFL, flags | O_NONBLOCK)) == -1
+ && errno == EINTR)
+ {
+ }
+ if (r == -1)
+ {
+ perror("fcntl");
+ exit(EXIT_FAILURE);
+ }
+}
+
+int
+create_listen_socket_tcp(uint32_t port)
+{
+ /* TODO: ipv6 */
+ struct addrinfo hints, *res, *rp;
+ int sfd = -1;
+ int r;
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
+ {
+ char sport[10];
+ snprintf(sport, 9, "%d", port);
+ r = getaddrinfo(0, sport, &hints, &res);
+ }
+ if (r != 0)
+ {
+ uint8_t buf[64];
+ snprintf((char *)buf, 63, "getaddrinfo: %s", gai_strerror(r));
+ log_msg(
+ buf, strlen((const char *)buf), wrdp_log_level_error, 0);
+ exit(EXIT_FAILURE);
+ }
+ for (rp = res; rp; rp = rp->ai_next)
+ {
+ int val = 1;
+ sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
+ if (sfd == -1)
+ {
+ continue;
+ }
+ if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &val,
+ (socklen_t)sizeof(val))
+ == -1)
+ {
+ continue;
+ }
+ if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0)
+ {
+ break;
+ }
+ close(sfd);
+ }
+ freeaddrinfo(res);
+ if (listen(sfd, 16) == -1)
+ {
+ perror("listen");
+ close(sfd);
+ exit(EXIT_FAILURE);
+ }
+ return sfd;
+}
+
+int
+create_listen_socket_unix(const char *path)
+{
+ struct sockaddr_un saddr;
+ int sfd = socket(AF_UNIX, SOCK_STREAM, 0);
+ bzero(&saddr, sizeof(struct sockaddr_un));
+ saddr.sun_family = AF_UNIX;
+ strcpy(saddr.sun_path, path);
+ /* this will delete file on disk, beware ) */
+ unlink(path);
+ if (bind(sfd, &saddr, sizeof(struct sockaddr_un)))
+ {
+ perror("bind");
+ exit(EXIT_FAILURE);
+ }
+ /* set permissive access to socket */
+ chmod(path, 0777);
+
+ if (listen(sfd, 16) == -1)
+ {
+ perror("listen");
+ close(sfd);
+ exit(EXIT_FAILURE);
+ }
+ return sfd;
+}
+
+int
+accept_new_connection(int socket)
+{
+ int fd = -1;
+ fd = accept(socket, NULL, NULL);
+ if (fd == -1 && errno != EINTR && errno != EAGAIN
+ && errno != EWOULDBLOCK)
+ {
+ perror("accept");
+ }
+ else
+ {
+ socket_make_non_block(fd);
+ }
+ return fd;
+}