aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlns <matzeton@googlemail.com>2022-05-03 01:17:31 +0200
committerlns <matzeton@googlemail.com>2022-05-03 01:17:31 +0200
commitd234d7a7b55d480650c794120431865160e6ba8c (patch)
treecce57c325b7c28c9818d9bd99a74231fa2b264e0
parent13ee4878ae57ddd30094044eb56014c4d5f5dfbd (diff)
...
Signed-off-by: lns <matzeton@googlemail.com>
-rw-r--r--src/pdesc.c6
-rw-r--r--src/pdesc.h6
-rw-r--r--src/psock.c138
-rw-r--r--src/psock.h6
-rw-r--r--src/ptunnel.c70
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;
}