diff options
-rw-r--r-- | apf_run.c | 17 | ||||
-rw-r--r-- | disassembler.c | 4 | ||||
-rw-r--r-- | v7/apf.h | 2 | ||||
-rw-r--r-- | v7/apf_interpreter.c | 28 | ||||
-rw-r--r-- | v7/apf_interpreter_source.c | 26 |
5 files changed, 52 insertions, 25 deletions
@@ -365,14 +365,19 @@ int main(int argc, char* argv[]) { } // Combine the program and data into the unified APF buffer. + uint32_t ram_len = program_len + data_len; + if (use_apf_v6_interpreter) { + ram_len += 3; + ram_len &= ~3; + if (data_len < 20) ram_len += 20; + } + if (data) { - program = realloc(program, program_len + data_len); - memcpy(program + program_len, data, data_len); + program = realloc(program, ram_len); + memcpy(program + ram_len - data_len, data, data_len); free(data); } - uint32_t ram_len = program_len + data_len; - if (filename) file_handler(use_apf_v6_interpreter, program, program_len, ram_len, filename, filter_age); @@ -382,11 +387,11 @@ int main(int argc, char* argv[]) { if (data_len) { printf("Data: "); - print_hex(program + program_len, data_len); + print_hex(program + ram_len - data_len, data_len); printf("\n"); if (print_counter_enabled) { printf("APF packet counters: \n"); - print_counter(program + program_len, data_len); + print_counter(program + ram_len - data_len, data_len); } } diff --git a/disassembler.c b/disassembler.c index 38b7eb2..2e93c3c 100644 --- a/disassembler.c +++ b/disassembler.c @@ -75,6 +75,7 @@ static const char* opcode_names [] = { [LDDW_OPCODE] = "lddw", [STDW_OPCODE] = "stdw", [WRITE_OPCODE] = "write", + [JNSET_OPCODE] = "jnset", }; static void print_jump_target(uint32_t target, uint32_t program_len) { @@ -174,7 +175,8 @@ const char* apf_disassemble(const uint8_t* program, uint32_t program_len, uint32 case JNE_OPCODE: case JGT_OPCODE: case JLT_OPCODE: - case JSET_OPCODE: { + case JSET_OPCODE: + case JNSET_OPCODE: { PRINT_OPCODE(); bprintf("r0, "); // Load second immediate field. @@ -210,6 +210,8 @@ typedef union { */ #define PKTDATACOPY_OPCODE 25 +#define JNSET_OPCODE 26 // JSET with reverse condition (jump if no bits set) + /* ---------------------------------------------------------------------------------------------- */ // Extended opcodes. diff --git a/v7/apf_interpreter.c b/v7/apf_interpreter.c index 56659e1..c4ef59e 100644 --- a/v7/apf_interpreter.c +++ b/v7/apf_interpreter.c @@ -266,6 +266,8 @@ typedef union { */ #define PKTDATACOPY_OPCODE 25 +#define JNSET_OPCODE 26 /* JSET with reverse condition (jump if no bits set) */ + /* ---------------------------------------------------------------------------------------------- */ /* Extended opcodes. */ @@ -661,6 +663,11 @@ static u32 decode_imm(apf_context* ctx, u32 length) { return v; } +/* Warning: 'ofs' should be validated by caller! */ +static u8 read_packet_u8(apf_context* ctx, u32 ofs) { + return ctx->packet[ofs]; +} + static int do_apf_run(apf_context* ctx) { /* Is offset within ram bounds? */ #define IN_RAM_BOUNDS(p) (ENFORCE_UNSIGNED(p) && (p) < ctx->ram_len) @@ -693,8 +700,9 @@ static int do_apf_run(apf_context* ctx) { /* Only populate if packet long enough, and IP version is IPv4. */ /* Note: this doesn't actually check the ethertype... */ - if ((ctx->packet_len >= ETH_HLEN + IPV4_HLEN) && ((ctx->packet[ETH_HLEN] & 0xf0) == 0x40)) { - ctx->mem.named.ipv4_header_size = (ctx->packet[ETH_HLEN] & 15) * 4; + if ((ctx->packet_len >= ETH_HLEN + IPV4_HLEN) + && ((read_packet_u8(ctx, ETH_HLEN) & 0xf0) == 0x40)) { + ctx->mem.named.ipv4_header_size = (read_packet_u8(ctx, ETH_HLEN) & 15) * 4; } /* Is access to offset |p| length |size| within output buffer bounds? */ @@ -781,7 +789,7 @@ static int do_apf_run(apf_context* ctx) { /* Catch overflow/wrap-around. */ ASSERT_RETURN(end_offs >= offs); ASSERT_IN_PACKET_BOUNDS(end_offs); - while (load_size--) val = (val << 8) | ctx->packet[offs++]; + while (load_size--) val = (val << 8) | read_packet_u8(ctx, offs++); REG = val; } break; @@ -800,7 +808,8 @@ static int do_apf_run(apf_context* ctx) { case JNE_OPCODE: case JGT_OPCODE: case JLT_OPCODE: - case JSET_OPCODE: { + case JSET_OPCODE: + case JNSET_OPCODE: { u32 cmp_imm = 0; /* Load second immediate field. */ if (reg_num == 1) { @@ -809,11 +818,12 @@ static int do_apf_run(apf_context* ctx) { cmp_imm = decode_imm(ctx, imm_len); /* 2nd imm, at worst 8 bytes past prog_len */ } switch (opcode) { - case JEQ_OPCODE: if (ctx->R[0] == cmp_imm) ctx->pc += imm; break; - case JNE_OPCODE: if (ctx->R[0] != cmp_imm) ctx->pc += imm; break; - case JGT_OPCODE: if (ctx->R[0] > cmp_imm) ctx->pc += imm; break; - case JLT_OPCODE: if (ctx->R[0] < cmp_imm) ctx->pc += imm; break; - case JSET_OPCODE: if (ctx->R[0] & cmp_imm) ctx->pc += imm; break; + case JEQ_OPCODE: if ( ctx->R[0] == cmp_imm ) ctx->pc += imm; break; + case JNE_OPCODE: if ( ctx->R[0] != cmp_imm ) ctx->pc += imm; break; + case JGT_OPCODE: if ( ctx->R[0] > cmp_imm ) ctx->pc += imm; break; + case JLT_OPCODE: if ( ctx->R[0] < cmp_imm ) ctx->pc += imm; break; + case JSET_OPCODE: if ( ctx->R[0] & cmp_imm ) ctx->pc += imm; break; + case JNSET_OPCODE: if (!(ctx->R[0] & cmp_imm)) ctx->pc += imm; break; } break; } diff --git a/v7/apf_interpreter_source.c b/v7/apf_interpreter_source.c index eb09d90..a36a4ee 100644 --- a/v7/apf_interpreter_source.c +++ b/v7/apf_interpreter_source.c @@ -117,6 +117,11 @@ static u32 decode_imm(apf_context* ctx, u32 length) { return v; } +// Warning: 'ofs' should be validated by caller! +static u8 read_packet_u8(apf_context* ctx, u32 ofs) { + return ctx->packet[ofs]; +} + static int do_apf_run(apf_context* ctx) { // Is offset within ram bounds? #define IN_RAM_BOUNDS(p) (ENFORCE_UNSIGNED(p) && (p) < ctx->ram_len) @@ -149,8 +154,9 @@ static int do_apf_run(apf_context* ctx) { // Only populate if packet long enough, and IP version is IPv4. // Note: this doesn't actually check the ethertype... - if ((ctx->packet_len >= ETH_HLEN + IPV4_HLEN) && ((ctx->packet[ETH_HLEN] & 0xf0) == 0x40)) { - ctx->mem.named.ipv4_header_size = (ctx->packet[ETH_HLEN] & 15) * 4; + if ((ctx->packet_len >= ETH_HLEN + IPV4_HLEN) + && ((read_packet_u8(ctx, ETH_HLEN) & 0xf0) == 0x40)) { + ctx->mem.named.ipv4_header_size = (read_packet_u8(ctx, ETH_HLEN) & 15) * 4; } // Is access to offset |p| length |size| within output buffer bounds? @@ -237,7 +243,7 @@ static int do_apf_run(apf_context* ctx) { // Catch overflow/wrap-around. ASSERT_RETURN(end_offs >= offs); ASSERT_IN_PACKET_BOUNDS(end_offs); - while (load_size--) val = (val << 8) | ctx->packet[offs++]; + while (load_size--) val = (val << 8) | read_packet_u8(ctx, offs++); REG = val; } break; @@ -256,7 +262,8 @@ static int do_apf_run(apf_context* ctx) { case JNE_OPCODE: case JGT_OPCODE: case JLT_OPCODE: - case JSET_OPCODE: { + case JSET_OPCODE: + case JNSET_OPCODE: { u32 cmp_imm = 0; // Load second immediate field. if (reg_num == 1) { @@ -265,11 +272,12 @@ static int do_apf_run(apf_context* ctx) { cmp_imm = decode_imm(ctx, imm_len); // 2nd imm, at worst 8 bytes past prog_len } switch (opcode) { - case JEQ_OPCODE: if (ctx->R[0] == cmp_imm) ctx->pc += imm; break; - case JNE_OPCODE: if (ctx->R[0] != cmp_imm) ctx->pc += imm; break; - case JGT_OPCODE: if (ctx->R[0] > cmp_imm) ctx->pc += imm; break; - case JLT_OPCODE: if (ctx->R[0] < cmp_imm) ctx->pc += imm; break; - case JSET_OPCODE: if (ctx->R[0] & cmp_imm) ctx->pc += imm; break; + case JEQ_OPCODE: if ( ctx->R[0] == cmp_imm ) ctx->pc += imm; break; + case JNE_OPCODE: if ( ctx->R[0] != cmp_imm ) ctx->pc += imm; break; + case JGT_OPCODE: if ( ctx->R[0] > cmp_imm ) ctx->pc += imm; break; + case JLT_OPCODE: if ( ctx->R[0] < cmp_imm ) ctx->pc += imm; break; + case JSET_OPCODE: if ( ctx->R[0] & cmp_imm ) ctx->pc += imm; break; + case JNSET_OPCODE: if (!(ctx->R[0] & cmp_imm)) ctx->pc += imm; break; } break; } |