1f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen/*
2f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen * Copyright 2016, The Android Open Source Project
3f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen *
4f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen * Licensed under the Apache License, Version 2.0 (the "License");
5f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen * you may not use this file except in compliance with the License.
6f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen * You may obtain a copy of the License at
7f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen *
8f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen * http://www.apache.org/licenses/LICENSE-2.0
9f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen *
10f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen * Unless required by applicable law or agreed to in writing, software
11f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen * distributed under the License is distributed on an "AS IS" BASIS,
12f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen * See the License for the specific language governing permissions and
14f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen * limitations under the License.
15f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen */
16f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen
17f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen// Simple program to try running an APF program against a packet.
18f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen
19f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen#include <libgen.h>
20f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen#include <stdint.h>
21f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen#include <stdio.h>
22f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen#include <stdlib.h>
23f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen#include <string.h>
24f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen
25f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen#include "apf_interpreter.h"
26f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen
27f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen// Parses hex in "input". Allocates and fills "*output" with parsed bytes.
28f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen// Returns length in bytes of "*output".
29f9491fa2795120de428ffcea3a113616b63644f3Paul Jensenint parse_hex(char* input, uint8_t** output) {
30f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen    int length = strlen(input);
31f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen    if (length & 1) {
32f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen        fprintf(stderr, "Argument not even number of characters: %s\n", input);
33f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen        exit(1);
34f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen    }
35f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen    length >>= 1;
36f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen    *output = malloc(length);
37f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen    if (*output == NULL) {
38f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen        fprintf(stderr, "Out of memory, tried to allocate %d\n", length);
39f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen        exit(1);
40f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen    }
41f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen    for (int i = 0; i < length; i++) {
42f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen        char byte[3] = { input[i*2], input[i*2+1], 0 };
43f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen        char* end_ptr;
44f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen        (*output)[i] = strtol(byte, &end_ptr, 16);
45f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen        if (end_ptr != byte + 2) {
46f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen            fprintf(stderr, "Failed to parse hex %s\n", byte);
47f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen            exit(1);
48f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen        }
49f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen    }
50f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen    return length;
51f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen}
52f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen
53ea115f501b42415063c4747e3b5bdc95e669fe1cBernie Innocentivoid print_hex(uint8_t* input, int len) {
54ea115f501b42415063c4747e3b5bdc95e669fe1cBernie Innocenti    for (int i = 0; i < len; ++i) {
55ea115f501b42415063c4747e3b5bdc95e669fe1cBernie Innocenti        printf("%02x", input[i]);
56ea115f501b42415063c4747e3b5bdc95e669fe1cBernie Innocenti    }
57ea115f501b42415063c4747e3b5bdc95e669fe1cBernie Innocenti}
58ea115f501b42415063c4747e3b5bdc95e669fe1cBernie Innocenti
59f9491fa2795120de428ffcea3a113616b63644f3Paul Jensenint main(int argc, char* argv[]) {
60ea115f501b42415063c4747e3b5bdc95e669fe1cBernie Innocenti    if (argc < 3 || argc > 5) {
61f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen        fprintf(stderr,
62ea115f501b42415063c4747e3b5bdc95e669fe1cBernie Innocenti                "Usage: %s <program> <packet> [<data>] [<age>]\n"
63f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen                "  program:     APF program, in hex\n"
64f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen                "  packet:      Packet to run through program, in hex\n"
65c206315b2faf7f0a59dbd64376de38e3d116534eErik Kline                "  data:        Data memory contents, in hex\n"
66ea115f501b42415063c4747e3b5bdc95e669fe1cBernie Innocenti                "  age:         Age of program in seconds (default: 0)\n",
67f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen                basename(argv[0]));
68f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen        exit(1);
69f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen    }
70f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen    uint8_t* program;
71f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen    uint32_t program_len = parse_hex(argv[1], &program);
72f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen    uint8_t* packet;
73f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen    uint32_t packet_len = parse_hex(argv[2], &packet);
74ea115f501b42415063c4747e3b5bdc95e669fe1cBernie Innocenti    uint8_t* data = NULL;
75ea115f501b42415063c4747e3b5bdc95e669fe1cBernie Innocenti    uint32_t data_len = argc > 3 ? parse_hex(argv[3], &data) : 0;
76ea115f501b42415063c4747e3b5bdc95e669fe1cBernie Innocenti    uint32_t filter_age = argc > 4 ? atoi(argv[4]) : 0;
77d2cc2b74f161d88bc0622b03d48ef176fefee03aBernie Innocenti
78d2cc2b74f161d88bc0622b03d48ef176fefee03aBernie Innocenti    // Combine the program and data into the unified APF buffer.
79ea115f501b42415063c4747e3b5bdc95e669fe1cBernie Innocenti    if (data) {
80d2cc2b74f161d88bc0622b03d48ef176fefee03aBernie Innocenti        program = realloc(program, program_len + data_len);
81d2cc2b74f161d88bc0622b03d48ef176fefee03aBernie Innocenti        memcpy(program + program_len, data, data_len);
82d2cc2b74f161d88bc0622b03d48ef176fefee03aBernie Innocenti        free(data);
83d2cc2b74f161d88bc0622b03d48ef176fefee03aBernie Innocenti    }
84d2cc2b74f161d88bc0622b03d48ef176fefee03aBernie Innocenti
85d2cc2b74f161d88bc0622b03d48ef176fefee03aBernie Innocenti    uint32_t ram_len = program_len + data_len;
86d2cc2b74f161d88bc0622b03d48ef176fefee03aBernie Innocenti    int ret = accept_packet(program, program_len, ram_len, packet, packet_len,
87d2cc2b74f161d88bc0622b03d48ef176fefee03aBernie Innocenti                            filter_age);
88d2cc2b74f161d88bc0622b03d48ef176fefee03aBernie Innocenti    printf("Packet %sed\n", ret ? "pass" : "dropp");
89d2cc2b74f161d88bc0622b03d48ef176fefee03aBernie Innocenti    if (data_len) {
90ea115f501b42415063c4747e3b5bdc95e669fe1cBernie Innocenti        printf("Data: ");
91d2cc2b74f161d88bc0622b03d48ef176fefee03aBernie Innocenti        print_hex(program + program_len, data_len);
92ea115f501b42415063c4747e3b5bdc95e669fe1cBernie Innocenti        printf("\n");
93ea115f501b42415063c4747e3b5bdc95e669fe1cBernie Innocenti    }
94f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen    free(program);
95f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen    free(packet);
96f9491fa2795120de428ffcea3a113616b63644f3Paul Jensen    return ret;
97ea115f501b42415063c4747e3b5bdc95e669fe1cBernie Innocenti}
98