summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apf_run.c17
-rw-r--r--disassembler.c4
-rw-r--r--v7/apf.h2
-rw-r--r--v7/apf_interpreter.c28
-rw-r--r--v7/apf_interpreter_source.c26
5 files changed, 52 insertions, 25 deletions
diff --git a/apf_run.c b/apf_run.c
index 4c63767..c2df5c1 100644
--- a/apf_run.c
+++ b/apf_run.c
@@ -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.
diff --git a/v7/apf.h b/v7/apf.h
index 29484eb..29f9785 100644
--- a/v7/apf.h
+++ b/v7/apf.h
@@ -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;
}