Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ add_executable(ef-tests
test/ef-tests.cxx
test/test-ef-parse-bytes.cxx
test/ifh-ignore.cxx
test/test-padding.cxx
)

target_link_libraries(ef-tests libef)
Expand Down
9 changes: 8 additions & 1 deletion src/ef-args.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ void print_help() {
po("Options:\n");
po(" -v Print version.\n");
po(" -h Top level help message.\n");
po(" -p No pad. Skip padding frames to 60 bytes,\n");
po(" allowing runt frames to be sent or matched as-is.\n");
po(" -t <timeout-in-ms> When listening on an interface (rx),\n");
po(" When listening on an interface (rx), the tool will always\n");
po(" listen during the entire timeout period. This is needed,\n");
Expand Down Expand Up @@ -320,13 +322,18 @@ int argc_cmds(int argc, const char *argv[]) {
return res;
}

int NO_PAD = 0;
int TIME_OUT_MS = 100;

int main_(int argc, const char *argv[]) {
int opt;

while ((opt = getopt(argc, (char * const*)argv, "vht:c:")) != -1) {
while ((opt = getopt(argc, (char * const*)argv, "pvht:c:")) != -1) {
switch (opt) {
case 'p':
NO_PAD = 1;
break;

case 'v':
print_version();
return 0;
Expand Down
4 changes: 2 additions & 2 deletions src/ef.c
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ buf_t *frame_to_buf(frame_t *f) {
frame_size += f->stack[i]->size;
}

if (frame_size < 60)
if (frame_size < 60 && !NO_PAD)
frame_size = 60;

buf = balloc(frame_size);
Expand All @@ -503,7 +503,7 @@ buf_t *frame_mask_to_buf(frame_t *f) {
}

frame_size_no_padding = frame_size;
if (frame_size < 60)
if (frame_size < 60 && !NO_PAD)
frame_size = 60;

buf = balloc(frame_size);
Expand Down
1 change: 1 addition & 0 deletions src/ef.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ extern "C" {
#define DIV_ROUND(a, b) (1 + ((a - 1) / b))
#define BIT_TO_BYTE(x) (DIV_ROUND(x, 8))

extern int NO_PAD;
extern int TIME_OUT_MS;

///////////////////////////////////////////////////////////////////////////////
Expand Down
98 changes: 98 additions & 0 deletions test/test-padding.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#include "ef.h"
#include "ef-test.h"
#include "catch_single_include.hxx"

#include <cstring>

// RAII guard to set NO_PAD for the duration of a scope
struct NoPadGuard {
NoPadGuard() { NO_PAD = 1; }
~NoPadGuard() { NO_PAD = 0; }
};

// Build a frame and its expected buf/mask from a frame spec
static void build_frame(std::vector<const char *> spec,
buf_t **out_buf, buf_t **out_mask,
frame_t **out_frame)
{
frame_t *f = parse_frame_wrap(spec);
REQUIRE(f != NULL);
*out_buf = frame_to_buf(f);
REQUIRE(*out_buf != NULL);
*out_mask = f->has_mask ? frame_mask_to_buf(f) : NULL;
*out_frame = f;
}

TEST_CASE("no-pad: eth-only frame is 14 bytes", "[nopad]") {
NoPadGuard g;
buf_t *buf, *mask;
frame_t *f;
build_frame({"eth", "dmac", "::1", "smac", "::2"}, &buf, &mask, &f);

// eth header = 14 bytes, no padding to 60
CHECK(buf->size == 14);

bfree(buf);
frame_free(f);
}

TEST_CASE("no-pad: default pads to 60 bytes", "[nopad]") {
CHECK(NO_PAD == 0);
buf_t *buf, *mask;
frame_t *f;
build_frame({"eth", "dmac", "::1", "smac", "::2"}, &buf, &mask, &f);

CHECK(buf->size == 60);

bfree(buf);
frame_free(f);
}

TEST_CASE("no-pad: mask buf also skips padding", "[nopad]") {
NoPadGuard g;

// Use 'ign' on smac to force mask generation
frame_t *f = parse_frame_wrap({"eth", "dmac", "::1", "smac", "ign"});
REQUIRE(f != NULL);
buf_t *buf = frame_to_buf(f);
buf_t *mask = frame_mask_to_buf(f);
REQUIRE(buf != NULL);
REQUIRE(mask != NULL);

CHECK(buf->size == 14);
CHECK(mask->size == 14);

bfree(buf);
bfree(mask);
frame_free(f);
}

TEST_CASE("no-pad: frame with payload stays exact size", "[nopad]") {
NoPadGuard g;
buf_t *buf, *mask;
frame_t *f;

// eth(14) + data pattern cnt 4 = 18 bytes, well under 60
build_frame({"eth", "dmac", "::1", "smac", "::2",
"data", "pattern", "cnt", "4"}, &buf, &mask, &f);

CHECK(buf->size == 18);

bfree(buf);
frame_free(f);
}

TEST_CASE("no-pad: large frame unaffected", "[nopad]") {
NoPadGuard g;
buf_t *buf, *mask;
frame_t *f;

// eth(14) + data pattern cnt 100 = 114 bytes, already > 60
build_frame({"eth", "dmac", "::1", "smac", "::2",
"data", "pattern", "cnt", "100"}, &buf, &mask, &f);

CHECK(buf->size == 114);

bfree(buf);
frame_free(f);
}