summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2018-12-11 04:12:40 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2018-12-11 04:12:40 +0000
commit726066e3ffe1a4e5ece4793f377b81a92232ecff (patch)
tree0ba9335da6b2ad9c2ea7791bc9bf12a7207006e6
parentb22072bd640a4a6bd839393f2e227847ae1a4ec4 (diff)
parent3fe31abd5b5ec0e131338b5469064110e811829c (diff)
downloadapf-726066e3ffe1a4e5ece4793f377b81a92232ecff.tar.gz
Snap for 5174203 from 3fe31abd5b5ec0e131338b5469064110e811829c to qt-release
Change-Id: I4450cedb1a7a58e987e79dad10e86061a404fa4a
-rw-r--r--Android.bp8
-rw-r--r--apf_run.c210
2 files changed, 197 insertions, 21 deletions
diff --git a/Android.bp b/Android.bp
index cddf41e..930d37d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -26,8 +26,16 @@ cc_binary_host {
cc_binary_host {
name: "apf_run",
defaults: ["apf_defaults"],
+ static_libs: [
+ "libpcap",
+ ],
srcs: [
"apf_run.c",
"apf_interpreter.c",
],
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
}
diff --git a/apf_run.c b/apf_run.c
index d485b71..5532762 100644
--- a/apf_run.c
+++ b/apf_run.c
@@ -16,7 +16,11 @@
// Simple program to try running an APF program against a packet.
+#include <errno.h>
+#include <getopt.h>
#include <libgen.h>
+#include <limits.h>
+#include <pcap.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -24,9 +28,27 @@
#include "apf_interpreter.h"
+enum {
+ OPT_PROGRAM,
+ OPT_PACKET,
+ OPT_PCAP,
+ OPT_DATA,
+ OPT_AGE
+};
+
+const struct option long_options[] = {
+ {"program", 1, NULL, OPT_PROGRAM},
+ {"packet", 1, NULL, OPT_PACKET},
+ {"pcap", 1, NULL, OPT_PCAP},
+ {"data", 1, NULL, OPT_DATA},
+ {"age", 1, NULL, OPT_AGE},
+ {"help", 0, NULL, 'h'},
+ {NULL, 0, NULL, 0}
+};
+
// Parses hex in "input". Allocates and fills "*output" with parsed bytes.
// Returns length in bytes of "*output".
-int parse_hex(char* input, uint8_t** output) {
+size_t parse_hex(const char* input, uint8_t** output) {
int length = strlen(input);
if (length & 1) {
fprintf(stderr, "Argument not even number of characters: %s\n", input);
@@ -50,30 +72,173 @@ int parse_hex(char* input, uint8_t** output) {
return length;
}
-void print_hex(uint8_t* input, int len) {
+void print_hex(const uint8_t* input, int len) {
for (int i = 0; i < len; ++i) {
printf("%02x", input[i]);
}
}
+// Process packet through APF filter
+void packet_handler(uint8_t* program, uint32_t program_len, uint32_t ram_len,
+ const char* pkt, uint32_t filter_age) {
+ uint8_t* packet;
+ uint32_t packet_len = parse_hex(pkt, &packet);
+
+ int ret = accept_packet(program, program_len, ram_len, packet, packet_len,
+ filter_age);
+ printf("Packet %sed\n", ret ? "pass" : "dropp");
+
+ free(packet);
+}
+
+// Process pcap file through APF filter and generate output files
+void file_handler(uint8_t* program, uint32_t program_len, uint32_t ram_len,
+ char* filename, uint32_t filter_age){
+ char errbuf[PCAP_ERRBUF_SIZE];
+ pcap_t *pcap;
+ struct pcap_pkthdr apf_header;
+ const uint8_t* apf_packet;
+ pcap_dumper_t *passed_dumper, *dropped_dumper;
+ const char passed_file[] = "passed.pcap";
+ const char dropped_file[] = "dropped.pcap";
+ int pass = 0;
+ int drop = 0;
+
+ pcap = pcap_open_offline(filename, errbuf);
+ if (pcap == NULL) {
+ printf("Open pcap file failed.\n");
+ exit(1);
+ }
+
+ passed_dumper = pcap_dump_open(pcap, passed_file);
+ dropped_dumper = pcap_dump_open(pcap, dropped_file);
+
+ if (!passed_dumper || !dropped_dumper) {
+ printf("pcap_dump_open(): open output file failed.\n");
+ pcap_close(pcap);
+ exit(1);
+ }
+
+ while ((apf_packet = pcap_next(pcap, &apf_header)) != NULL) {
+ int result = accept_packet(program, program_len, ram_len, apf_packet,
+ apf_header.len, filter_age);
+
+ if (!result){
+ drop++;
+ pcap_dump((u_char*)dropped_dumper, &apf_header, apf_packet);
+ } else {
+ pass++;
+ pcap_dump((u_char*)passed_dumper, &apf_header, apf_packet);
+ }
+ }
+
+ printf("%d packets dropped\n", drop);
+ printf("%d packets passed\n", pass);
+ pcap_dump_close(passed_dumper);
+ pcap_dump_close(dropped_dumper);
+ pcap_close(pcap);
+}
+
+void print_usage(char* cmd) {
+ fprintf(stderr,
+ "Usage: %s --program <program> --pcap <file>|--packet <packet> "
+ "[--data <content>] [--age <number>]\n"
+ " --program APF program, in hex.\n"
+ " --pcap Pcap file to run through program.\n"
+ " --packet Packet to run through program.\n"
+ " --data Data memory contents, in hex.\n"
+ " --age Age of program in seconds (default: 0).\n"
+ " -h, --help Show this message.\n",
+ basename(cmd));
+}
+
int main(int argc, char* argv[]) {
- if (argc < 3 || argc > 5) {
- fprintf(stderr,
- "Usage: %s <program> <packet> [<data>] [<age>]\n"
- " program: APF program, in hex\n"
- " packet: Packet to run through program, in hex\n"
- " data: Data memory contents, in hex\n"
- " age: Age of program in seconds (default: 0)\n",
- basename(argv[0]));
+ if (argc > 9) {
+ print_usage(argv[0]);
exit(1);
}
- uint8_t* program;
- uint32_t program_len = parse_hex(argv[1], &program);
- uint8_t* packet;
- uint32_t packet_len = parse_hex(argv[2], &packet);
+
+ uint8_t* program = NULL;
+ uint32_t program_len;
+ char *filename = NULL;
+ char* packet = NULL;
uint8_t* data = NULL;
- uint32_t data_len = argc > 3 ? parse_hex(argv[3], &data) : 0;
- uint32_t filter_age = argc > 4 ? atoi(argv[4]) : 0;
+ uint32_t data_len = 0;
+ int32_t filter_age = 0;
+
+ int opt;
+ char *endptr;
+
+ while ((opt = getopt_long_only(argc, argv, "h", long_options, NULL)) != -1) {
+ switch (opt) {
+ case OPT_PROGRAM:
+ program_len = parse_hex(optarg, &program);
+ break;
+ case OPT_PACKET:
+ if (!program) {
+ printf("<packet> requires <program> first\n\'%s -h or --help\' "
+ "for more information\n", basename(argv[0]));
+ exit(1);
+ }
+ if (filename) {
+ printf("Cannot use <file> with <packet> \n\'%s -h or --help\' "
+ "for more information\n", basename(argv[0]));
+
+ exit(1);
+ }
+ packet = optarg;
+ break;
+ case OPT_PCAP:
+ if (!program) {
+ printf("<file> requires <program> first\n\'%s -h or --help\' "
+ "for more information\n", basename(argv[0]));
+
+ exit(1);
+ }
+ if (packet) {
+ printf("Cannot use <packet> with <file>\n\'%s -h or --help\' "
+ "for more information\n", basename(argv[0]));
+
+ exit(1);
+ }
+ filename = optarg;
+ break;
+ case OPT_DATA:
+ data_len = parse_hex(optarg, &data);
+ break;
+ case OPT_AGE:
+ errno = 0;
+ filter_age = strtoul(optarg, &endptr, 10);
+ if ((errno == ERANGE && filter_age == ULONG_MAX)
+ || (errno != 0 && filter_age == 0)) {
+ perror("Error on age option: strtoul");
+ exit(1);
+ }
+ if (endptr == optarg) {
+ printf("No digit found in age.\n");
+ exit(1);
+ }
+ break;
+ case 'h':
+ print_usage(argv[0]);
+ exit(0);
+ break;
+ default:
+ print_usage(argv[0]);
+ exit(1);
+ break;
+ }
+ }
+
+ if (!program) {
+ printf("Must have APF program in option.\n");
+ exit(1);
+ }
+
+ if (!filename && !packet) {
+ printf("Missing file or packet after program.\n");
+ exit(1);
+ }
// Combine the program and data into the unified APF buffer.
if (data) {
@@ -83,15 +248,18 @@ int main(int argc, char* argv[]) {
}
uint32_t ram_len = program_len + data_len;
- int ret = accept_packet(program, program_len, ram_len, packet, packet_len,
- filter_age);
- printf("Packet %sed\n", ret ? "pass" : "dropp");
+
+ if (filename)
+ file_handler(program, program_len, ram_len, filename, filter_age);
+ else
+ packet_handler(program, program_len, ram_len, packet, filter_age);
+
if (data_len) {
printf("Data: ");
print_hex(program + program_len, data_len);
printf("\n");
}
+
free(program);
- free(packet);
- return ret;
+ return 0;
}