diff options
author | lns <matzeton@googlemail.com> | 2022-05-03 01:17:31 +0200 |
---|---|---|
committer | lns <matzeton@googlemail.com> | 2022-05-03 01:17:31 +0200 |
commit | d234d7a7b55d480650c794120431865160e6ba8c (patch) | |
tree | cce57c325b7c28c9818d9bd99a74231fa2b264e0 | |
parent | 13ee4878ae57ddd30094044eb56014c4d5f5dfbd (diff) |
...
Signed-off-by: lns <matzeton@googlemail.com>
-rw-r--r-- | src/pdesc.c | 6 | ||||
-rw-r--r-- | src/pdesc.h | 6 | ||||
-rw-r--r-- | src/psock.c | 138 | ||||
-rw-r--r-- | src/psock.h | 6 | ||||
-rw-r--r-- | src/ptunnel.c | 70 |
5 files changed, 173 insertions, 53 deletions
diff --git a/src/pdesc.c b/src/pdesc.c index 84c6f70..4ffd7f5 100644 --- a/src/pdesc.c +++ b/src/pdesc.c @@ -12,7 +12,7 @@ static void pdesc_init(struct psock * sock, struct pdesc * desc, uint16_t identi desc->sequence = 0; } -enum pdesc_remote_errno pdesc_find_remote(struct psock * sock, struct pdesc ** const desc) +enum pdesc_remote_errno pdesc_find_current_remote(struct psock * sock, struct pdesc ** const desc) { size_t i; @@ -33,7 +33,7 @@ enum pdesc_remote_errno pdesc_find_remote(struct psock * sock, struct pdesc ** c for (i = 0; i < sock->remotes.used; ++i) { if (sock->current.packet.icmphdr->un.echo.id == sock->remotes.descriptors[i].identifier) { *desc = &sock->remotes.descriptors[i]; - return REMOTE_FOUND; + return REMOTE_EXISTS; } } if (i == sock->remotes.max) { @@ -43,5 +43,5 @@ enum pdesc_remote_errno pdesc_find_remote(struct psock * sock, struct pdesc ** c pdesc_init(sock, &sock->remotes.descriptors[i], sock->current.packet.icmphdr->un.echo.id); *desc = &sock->remotes.descriptors[i]; - return REMOTE_FOUND; + return REMOTE_NOT_FOUND; } diff --git a/src/pdesc.h b/src/pdesc.h index b0355b4..dcba303 100644 --- a/src/pdesc.h +++ b/src/pdesc.h @@ -7,7 +7,8 @@ struct psock; enum pdesc_remote_errno { - REMOTE_FOUND, + REMOTE_EXISTS, + REMOTE_NOT_FOUND, REMOTE_PACKET_INVALID, REMOTE_ICMP_ECHO_CLIENT, REMOTE_ICMP_REPLY_SERVER, @@ -19,10 +20,11 @@ enum pdesc_state { PDESC_STATE_AUTH, PDESC_STATE_DATA }; struct pdesc { enum pdesc_state state; struct sockaddr_storage peer; + char peer_str[INET6_ADDRSTRLEN]; uint16_t identifier; uint16_t sequence; }; -enum pdesc_remote_errno pdesc_find_remote(struct psock *, struct pdesc ** const); +enum pdesc_remote_errno pdesc_find_current_remote(struct psock *, struct pdesc ** const); #endif diff --git a/src/psock.c b/src/psock.c index c88ec56..548be93 100644 --- a/src/psock.c +++ b/src/psock.c @@ -1,20 +1,48 @@ #include "pdesc.h" #include "psock.h" #include "ppkt.h" +#include "putils.h" +#include <arpa/inet.h> #include <errno.h> +#include <netdb.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/epoll.h> #include <sys/socket.h> +#include <sys/types.h> #include <unistd.h> -int psock_init(struct psock * sock, int is_client, size_t max_descriptors, size_t packet_buffer_size) +int psock_init(struct psock * sock, size_t max_descriptors, size_t packet_buffer_size) +{ + memset(sock, 0, sizeof(*sock)); + + sock->current.packet.max = packet_buffer_size; + sock->current.packet.used = 0; + sock->current.packet.buffer = (uint8_t *)calloc(packet_buffer_size, sizeof(*sock->current.packet.buffer)); + if (sock->current.packet.buffer == NULL) { + goto error; + } + + sock->remotes.max = max_descriptors; + sock->remotes.used = 0; + sock->remotes.descriptors = (struct pdesc *)calloc(max_descriptors, sizeof(*sock->remotes.descriptors)); + if (sock->remotes.descriptors == NULL) { + goto error; + } + + return 0; +error: + psock_free(sock); + return -1; +} + +int psock_setup_fds(struct psock * sock, int is_client) { struct epoll_event ev; - memset(sock, 0, sizeof(*sock)); + errno = 0; sock->icmp_fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); if (sock->icmp_fd < 0) { @@ -33,32 +61,95 @@ int psock_init(struct psock * sock, int is_client, size_t max_descriptors, size_ } sock->local.is_client = is_client; - - sock->current.packet.max = packet_buffer_size; - sock->current.packet.used = 0; - sock->current.packet.buffer = (uint8_t *)calloc(packet_buffer_size, sizeof(*sock->current.packet.buffer)); - if (sock->current.packet.buffer == NULL) { - goto error; - } - - sock->remotes.max = max_descriptors; - sock->remotes.used = 0; - sock->remotes.descriptors = (struct pdesc *)calloc(max_descriptors, sizeof(*sock->remotes.descriptors)); - if (sock->remotes.descriptors == NULL) { - goto error; - } - return 0; error: if (errno != 0) { - perror("[FATAL] psock_init failed"); + logger(1, "file descriptor setup failed: %s", strerror(errno)); } psock_free(sock); return -1; } -int psock_add_server(char const * const address) +static int psock_name_to_address(char const * address, struct sockaddr_storage * const sockaddr, size_t * sockaddr_size) +{ + struct addrinfo hints = {}; + struct addrinfo *result, *rp; + int ret; + + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_flags = AI_PASSIVE; + + ret = getaddrinfo(address, NULL, &hints, &result); + if (ret != 0) { + logger_early(1, "Could not add server '%s': %s", address, gai_strerror(ret)); + return ret; + } + + size_t i = 0; + for (rp = result; rp != NULL; rp = rp->ai_next) { + if (i == *sockaddr_size) { + break; + } + switch (rp->ai_family) { + case AF_INET: { + memcpy(&sockaddr[i++], rp->ai_addr, sizeof(struct sockaddr_in)); + break; + } + case AF_INET6: { + memcpy(&sockaddr[i++], rp->ai_addr, sizeof(struct sockaddr_in6)); + break; + } + default: + logger_early(1, "getaddrinfo() returned an invalid address family: %d", rp->ai_family); + break; + } + } + *sockaddr_size = i; + + freeaddrinfo(result); + return ret; +} + +int psock_add_server(struct psock * sock, char const * address) { + size_t max_sockaddrs = 8; + struct sockaddr_storage sockaddrs[max_sockaddrs]; + + if (psock_name_to_address(address, sockaddrs, &max_sockaddrs) != 0) { + return -1; + } + + for (size_t addr_i = 0; sock->remotes.used < sock->remotes.max && addr_i < max_sockaddrs; + ++sock->remotes.used, ++addr_i) { + size_t desc_i = sock->remotes.used; + + switch (sockaddrs[addr_i].ss_family) { + case AF_INET: { + struct in_addr addr = ((struct sockaddr_in *)&sockaddrs[addr_i])->sin_addr; + if (inet_ntop(AF_INET, &addr, sock->remotes.descriptors[desc_i].peer_str, sizeof(struct sockaddr_in)) == + NULL) { + logger_early(1, "inet_ntop() conversion failed: %s", strerror(errno)); + return -1; + } + break; + } + case AF_INET6: { + struct in6_addr addr = ((struct sockaddr_in6 *)&sockaddrs[addr_i])->sin6_addr; + if (inet_ntop(AF_INET6, + &addr, + sock->remotes.descriptors[desc_i].peer_str, + sizeof(struct sockaddr_in6)) == NULL) { + logger_early(1, "inet_ntop() conversion failed: %s", strerror(errno)); + return -1; + } + break; + } + } + logger_early(0, "Added remote: %s", sock->remotes.descriptors[desc_i].peer_str); + } + + return 0; } void psock_free(struct psock * sock) @@ -130,9 +221,12 @@ static void psock_handle_events(struct psock * sock) if (psock_recvmsg(sock) == 0) { struct pdesc * remote; - switch (pdesc_find_remote(sock, &remote)) { - case REMOTE_FOUND: - printf("Remote descriptor ID: %u\n", remote->identifier); + switch (pdesc_find_current_remote(sock, &remote)) { + case REMOTE_EXISTS: + printf("Existing Remote with descriptor ID: %u\n", remote->identifier); + break; + case REMOTE_NOT_FOUND: + printf("New Remote with descriptor ID: %u\n", remote->identifier); break; case REMOTE_PACKET_INVALID: fprintf(stderr, "Invalid packet received.\n"); diff --git a/src/psock.h b/src/psock.h index ab51bc5..eb00070 100644 --- a/src/psock.h +++ b/src/psock.h @@ -36,9 +36,11 @@ struct psock { } remotes; }; -int psock_init(struct psock *, int, size_t, size_t); +int psock_init(struct psock *, size_t, size_t); -int psock_add_server(char const *); +int psock_setup_fds(struct psock *, int); + +int psock_add_server(struct psock *, char const *); void psock_free(struct psock *); diff --git a/src/ptunnel.c b/src/ptunnel.c index dce1a7f..6b2b815 100644 --- a/src/ptunnel.c +++ b/src/ptunnel.c @@ -9,35 +9,40 @@ static struct { int is_client; - struct { - char * str; - } address; -} ptunnel_options = {.is_client = 0}; + int log_to_console; +} ptunnel_options = {.is_client = 0, .log_to_console = 0}; -int parse_options(int argc, char ** argv) +int parse_options(struct psock * sock, int argc, char ** argv) { - int opt; + int ret = 0, opt; - while ((opt = getopt(argc, argv, "ca:")) != -1) { + while ((opt = getopt(argc, argv, "lca:")) != -1) { switch (opt) { + case 'l': + ptunnel_options.log_to_console = 1; + enable_console_logger(); + break; case 'c': ptunnel_options.is_client = 1; break; case 'a': - ptunnel_options.address.str = strdup(optarg); + if (psock_add_server(sock, optarg) != 0) { + logger_early(1, "Could not add server: %s", optarg); + ret++; + } break; } } - return 0; + return ret; } -int validate_options(void) +int validate_options(struct psock const * sock) { logger_early(0, "Running in %s mode.", (ptunnel_options.is_client == 0 ? "proxy" : "forward")); - if (ptunnel_options.is_client != 0 && ptunnel_options.address.str == NULL) { - logger_early(1, "An adress (`-a') is mandatory in forward mode."); + if (ptunnel_options.is_client != 0 && sock->remotes.used == 0) { + logger_early(1, "An address (`-a') is mandatory in forward mode."); return -1; } @@ -46,29 +51,46 @@ int validate_options(void) int main(int argc, char ** argv) { - struct psock psock = {}; + int ret = 0; + struct psock sock = {}; init_logging("ptunnel-ng"); - enable_console_logger(); - - if (parse_options(argc, argv) != 0) { - return 1; + if (psock_init(&sock, 16, 1500) != 0) { + logger(1, "%s", "Socket initialization failed"); + ret++; + goto failure; } - if (validate_options() != 0) { - return 1; + ret += parse_options(&sock, argc, argv); + if (ret != 0) { + logger_early(1, "Command line option parsing failed: %d argument(s)", ret); + ret++; + goto failure; } - if (psock_init(&psock, ptunnel_options.is_client, 16, 1500) != 0) { - return 1; + shutdown_logging(); + init_logging((ptunnel_options.is_client == 0 ? "ptunnel-ng-proxy" : "ptunnel-ng-forwarder")); + if (ptunnel_options.log_to_console != 0) { + enable_console_logger(); } - psock_loop(&psock); + if (validate_options(&sock) != 0) { + logger(1, "%s", "Command line validation failed"); + ret++; + goto failure; + } - psock_free(&psock); + if (psock_setup_fds(&sock, ptunnel_options.is_client) != 0) { + logger(1, "%s", "Socket setup failed"); + ret++; + goto failure; + } + psock_loop(&sock); +failure: + psock_free(&sock); shutdown_logging(); - return 0; + return ret; } |