From 3b9029a94641563b9dda4f75694e499be9366d0a Mon Sep 17 00:00:00 2001 From: mrb0nk500 Date: Thu, 10 Jun 2021 23:20:38 -0400 Subject: Finished `init_socket()`. --- pullreqd.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 3 deletions(-) diff --git a/pullreqd.c b/pullreqd.c index b3029ae..a4501c6 100644 --- a/pullreqd.c +++ b/pullreqd.c @@ -15,6 +15,8 @@ #include #include "config.h" +#define UNIX_PATH_MAX 108 + pid_t fork_proc() { /* Fork off the parent. */ pid_t pid = fork(); @@ -91,17 +93,82 @@ int init_socket(config *cfg) { struct sockaddr_un sa_un; struct sockaddr_in sa_in; } sock_addr; + /* Size of the socket address we're using. */ + size_t sockaddr_size = 0; /* Set socket type to unix socket, if socket-type was set to unix, otherwise set it to network socket. */ const int sock_type = (!strcasecmp(cfg->sock_type, "unix")) ? AF_UNIX : AF_INET; + + if (sock_type == AF_UNIX) { + size_t path_length = strlen(cfg->sock); + if (path_length >= UNIX_PATH_MAX) { + syslog(LOG_ERR, "The socket path is too long, and exceeded %i characters.", UNIX_PATH_MAX); + return -1; + } + + sockaddr_size = sizeof(sock_addr.sa_un); + sock_addr.sa_un.sun_family = sock_type; + memcpy(sock_addr.sa_un.sun_path, cfg->sock, path_length+1); + } else { + if (cfg->port <= 0 || cfg->port > 65535) { + syslog(LOG_ERR, "Invalid port %d. (Valid port must be between 1, and 65535.)", cfg->port); + return -1; + } + struct addrinfo hints, *ainfo_root, *ainfo; + const size_t size = sprintf(NULL, "%d", cfg->port) + 1; + char *port_str = malloc(size); + + sprintf(port_str, "%d", cfg->port); + memset(&hints, 0, sizeof(hints)); + + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_SEQPACKET; + /*hints.ai_protocol = IPPROTO_SCTP;*/ + hints.ai_flags = AI_PASSIVE; + + const int gai_ret = getaddrinfo(cfg->sock, port_str, &hints, &ainfo_root); + /* Did getaddrinfo fail? */ + if (gai_ret) { + syslog(LOG_ERR, "getaddrinfo() failed for hostname %s. Reason: %s", cfg->sock, gai_strerror(gai_ret)); + return -1; + } + + /* TODO: Create sockets for all resolved addresses, instead of just the first. */ + sockaddr_size = ainfo_root->ai_addrlen; + sock_addr.sa = *ainfo_root->ai_addr; + + freeaddrinfo(ainfo_root); + } + /* Create a new listen socket. */ - int fd = socket(sock_type, SOCK_SEQPACKET, 0); + int fd = socket(sock_addr.sa.sa_family, SOCK_SEQPACKET, 0); - /* TODO: Add rest of init code. */ + /* Did we fail to create the listen socket? */ + if (fd < 0) { + syslog(LOG_ERR, "Failed to create listen socket."); + return -1; + } - if (sock_type == AF_UNIX) { + /* Did we fail to bind the listen socket? */ + if (bind(fd, &sock_addr.sa, sockaddr_size) < 0) { + syslog(LOG_ERR, "Failed to bind listen socket."); + return -1; + } + + int one = 1; + + /* Did we fail to enable SO_REUSEADDR? */ + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) { + syslog(LOG_ERR, "Failed to enable SO_REUSEADDR."); + return -1; + } + /* Did we fail to listen to the socket? */ + if (listen(fd, 20) < 0) { + syslog(LOG_ERR, "Failed to listen to socket."); + return -1; } + syslog(LOG_INFO, "Successfully created socket descriptor %i for address %s.", fd, cfg->sock); return fd; } -- cgit v1.2.3-13-gbd6f