/* BSD-2-Clause license * * Copyright (c) 2018-2023 NST , sss . * */ #include #include #include #include #include #include #include #include #include #include #include #include #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; }