/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.net.apf;

import android.net.apf.ApfGenerator;
import android.net.apf.ApfGenerator.IllegalInstructionException;
import android.net.apf.ApfGenerator.Register;

import java.io.BufferedReader;
import java.io.InputStreamReader;

/**
 * BPF to APF translator.
 *
 * Note: This is for testing purposes only and is not guaranteed to support
 *       translation of all BPF programs.
 *
 * Example usage:
 *   javac net/java/android/net/apf/ApfGenerator.java \
 *         tests/servicestests/src/android/net/apf/Bpf2Apf.java
 *   sudo tcpdump -i em1 -d icmp | java -classpath tests/servicestests/src:net/java \
 *                                      android.net.apf.Bpf2Apf
 */
public class Bpf2Apf {
    private static int parseImm(String line, String arg) {
        if (!arg.startsWith("#0x")) {
            throw new IllegalArgumentException("Unhandled instruction: " + line);
        }
        final long val_long = Long.parseLong(arg.substring(3), 16);
        if (val_long < 0 || val_long > Long.parseLong("ffffffff", 16)) {
            throw new IllegalArgumentException("Unhandled instruction: " + line);
        }
        return new Long((val_long << 32) >> 32).intValue();
    }

    /**
     * Convert a single line of "tcpdump -d" (human readable BPF program dump) {@code line} into
     * APF instruction(s) and append them to {@code gen}. Here's an example line:
     * (001) jeq      #0x86dd          jt 2    jf 7
     */
    private static void convertLine(String line, ApfGenerator gen)
            throws IllegalInstructionException {
        if (line.indexOf("(") != 0 || line.indexOf(")") != 4 || line.indexOf(" ") != 5) {
            throw new IllegalArgumentException("Unhandled instruction: " + line);
        }
        int label = Integer.parseInt(line.substring(1, 4));
        gen.defineLabel(Integer.toString(label));
        String opcode = line.substring(6, 10).trim();
        String arg = line.substring(15, Math.min(32, line.length())).trim();
        switch (opcode) {
            case "ld":
            case "ldh":
            case "ldb":
            case "ldx":
            case "ldxb":
            case "ldxh":
                Register dest = opcode.contains("x") ? Register.R1 : Register.R0;
                if (arg.equals("4*([14]&0xf)")) {
                    if (!opcode.equals("ldxb")) {
                        throw new IllegalArgumentException("Unhandled instruction: " + line);
                    }
                    gen.addLoadFromMemory(dest, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
                    break;
                }
                if (arg.equals("#pktlen")) {
                    if (!opcode.equals("ld")) {
                        throw new IllegalArgumentException("Unhandled instruction: " + line);
                    }
                    gen.addLoadFromMemory(dest, gen.PACKET_SIZE_MEMORY_SLOT);
                    break;
                }
                if (arg.startsWith("#0x")) {
                    if (!opcode.equals("ld")) {
                        throw new IllegalArgumentException("Unhandled instruction: " + line);
                    }
                    gen.addLoadImmediate(dest, parseImm(line, arg));
                    break;
                }
                if (arg.startsWith("M[")) {
                    if (!opcode.startsWith("ld")) {
                        throw new IllegalArgumentException("Unhandled instruction: " + line);
                    }
                    int memory_slot = Integer.parseInt(arg.substring(2, arg.length() - 1));
                    if (memory_slot < 0 || memory_slot >= gen.MEMORY_SLOTS ||
                            // Disallow use of pre-filled slots as BPF programs might
                            // wrongfully assume they're initialized to 0.
                            (memory_slot >= gen.FIRST_PREFILLED_MEMORY_SLOT &&
                                    memory_slot <= gen.LAST_PREFILLED_MEMORY_SLOT)) {
                        throw new IllegalArgumentException("Unhandled instruction: " + line);
                    }
                    gen.addLoadFromMemory(dest, memory_slot);
                    break;
                }
                if (arg.startsWith("[x + ")) {
                    int offset = Integer.parseInt(arg.substring(5, arg.length() - 1));
                    switch (opcode) {
                        case "ld":
                        case "ldx":
                            gen.addLoad32Indexed(dest, offset);
                            break;
                        case "ldh":
                        case "ldxh":
                            gen.addLoad16Indexed(dest, offset);
                            break;
                        case "ldb":
                        case "ldxb":
                            gen.addLoad8Indexed(dest, offset);
                            break;
                    }
                } else {
                    int offset = Integer.parseInt(arg.substring(1, arg.length() - 1));
                    switch (opcode) {
                        case "ld":
                        case "ldx":
                            gen.addLoad32(dest, offset);
                            break;
                        case "ldh":
                        case "ldxh":
                            gen.addLoad16(dest, offset);
                            break;
                        case "ldb":
                        case "ldxb":
                            gen.addLoad8(dest, offset);
                            break;
                    }
                }
                break;
            case "st":
            case "stx":
                Register src = opcode.contains("x") ? Register.R1 : Register.R0;
                if (!arg.startsWith("M[")) {
                    throw new IllegalArgumentException("Unhandled instruction: " + line);
                }
                int memory_slot = Integer.parseInt(arg.substring(2, arg.length() - 1));
                if (memory_slot < 0 || memory_slot >= gen.MEMORY_SLOTS ||
                        // Disallow overwriting pre-filled slots
                        (memory_slot >= gen.FIRST_PREFILLED_MEMORY_SLOT &&
                                memory_slot <= gen.LAST_PREFILLED_MEMORY_SLOT)) {
                    throw new IllegalArgumentException("Unhandled instruction: " + line);
                }
                gen.addStoreToMemory(src, memory_slot);
                break;
            case "add":
            case "and":
            case "or":
            case "sub":
                if (arg.equals("x")) {
                    switch(opcode) {
                        case "add":
                            gen.addAddR1();
                            break;
                        case "and":
                            gen.addAndR1();
                            break;
                        case "or":
                            gen.addOrR1();
                            break;
                        case "sub":
                            gen.addNeg(Register.R1);
                            gen.addAddR1();
                            gen.addNeg(Register.R1);
                            break;
                    }
                } else {
                    int imm = parseImm(line, arg);
                    switch(opcode) {
                        case "add":
                            gen.addAdd(imm);
                            break;
                        case "and":
                            gen.addAnd(imm);
                            break;
                        case "or":
                            gen.addOr(imm);
                            break;
                        case "sub":
                            gen.addAdd(-imm);
                            break;
                    }
                }
                break;
            case "jeq":
            case "jset":
            case "jgt":
            case "jge":
                int val = 0;
                boolean reg_compare;
                if (arg.startsWith("x")) {
                    reg_compare = true;
                } else {
                    reg_compare = false;
                    val = parseImm(line, arg);
                }
                int jt_offset = line.indexOf("jt");
                int jf_offset = line.indexOf("jf");
                String true_label = line.substring(jt_offset + 2, jf_offset).trim();
                String false_label = line.substring(jf_offset + 2).trim();
                boolean true_label_is_fallthrough = Integer.parseInt(true_label) == label + 1;
                boolean false_label_is_fallthrough = Integer.parseInt(false_label) == label + 1;
                if (true_label_is_fallthrough && false_label_is_fallthrough)
                    break;
                switch (opcode) {
                    case "jeq":
                        if (!true_label_is_fallthrough) {
                            if (reg_compare) {
                                gen.addJumpIfR0EqualsR1(true_label);
                            } else {
                                gen.addJumpIfR0Equals(val, true_label);
                            }
                        }
                        if (!false_label_is_fallthrough) {
                            if (!true_label_is_fallthrough) {
                                gen.addJump(false_label);
                            } else if (reg_compare) {
                                gen.addJumpIfR0NotEqualsR1(false_label);
                            } else {
                                gen.addJumpIfR0NotEquals(val, false_label);
                            }
                        }
                        break;
                    case "jset":
                        if (reg_compare) {
                            gen.addJumpIfR0AnyBitsSetR1(true_label);
                        } else {
                            gen.addJumpIfR0AnyBitsSet(val, true_label);
                        }
                        if (!false_label_is_fallthrough) {
                            gen.addJump(false_label);
                        }
                        break;
                    case "jgt":
                        if (!true_label_is_fallthrough ||
                                // We have no less-than-or-equal-to register to register
                                // comparison instruction, so in this case we'll jump
                                // around an unconditional jump.
                                (!false_label_is_fallthrough && reg_compare)) {
                            if (reg_compare) {
                                gen.addJumpIfR0GreaterThanR1(true_label);
                            } else {
                                gen.addJumpIfR0GreaterThan(val, true_label);
                            }
                        }
                        if (!false_label_is_fallthrough) {
                            if (!true_label_is_fallthrough || reg_compare) {
                                gen.addJump(false_label);
                            } else {
                                gen.addJumpIfR0LessThan(val + 1, false_label);
                            }
                        }
                        break;
                    case "jge":
                        if (!false_label_is_fallthrough ||
                                // We have no greater-than-or-equal-to register to register
                                // comparison instruction, so in this case we'll jump
                                // around an unconditional jump.
                                (!true_label_is_fallthrough && reg_compare)) {
                            if (reg_compare) {
                                gen.addJumpIfR0LessThanR1(false_label);
                            } else {
                                gen.addJumpIfR0LessThan(val, false_label);
                            }
                        }
                        if (!true_label_is_fallthrough) {
                            if (!false_label_is_fallthrough || reg_compare) {
                                gen.addJump(true_label);
                            } else {
                                gen.addJumpIfR0GreaterThan(val - 1, true_label);
                            }
                        }
                        break;
                }
                break;
            case "ret":
                if (arg.equals("#0")) {
                    gen.addJump(gen.DROP_LABEL);
                } else {
                    gen.addJump(gen.PASS_LABEL);
                }
                break;
            case "tax":
                gen.addMove(Register.R1);
                break;
            case "txa":
                gen.addMove(Register.R0);
                break;
            default:
                throw new IllegalArgumentException("Unhandled instruction: " + line);
        }
    }

    /**
     * Convert the output of "tcpdump -d" (human readable BPF program dump) {@code bpf} into an APF
     * program and return it.
     */
    public static byte[] convert(String bpf) throws IllegalInstructionException {
        ApfGenerator gen = new ApfGenerator();
        for (String line : bpf.split("\\n")) convertLine(line, gen);
        return gen.generate();
    }

    /**
     * Convert the output of "tcpdump -d" (human readable BPF program dump) piped in stdin into an
     * APF program and output it via stdout.
     */
    public static void main(String[] args) throws Exception {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String line = null;
        StringBuilder responseData = new StringBuilder();
        ApfGenerator gen = new ApfGenerator();
        while ((line = in.readLine()) != null) convertLine(line, gen);
        System.out.write(gen.generate());
    }
}
