/*
 * Xtables BPF extension
 *
 * Written by Willem de Bruijn (willemb@google.com)
 * Copyright Google, Inc. 2013
 * Licensed under the GNU General Public License version 2 (GPLv2)
*/

#include <linux/netfilter/xt_bpf.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <xtables.h>

#define BCODE_FILE_MAX_LEN_B	1024

enum {
	O_BCODE_STDIN = 0,
};

static void bpf_help(void)
{
	printf(
"bpf match options:\n"
"--bytecode <program>	: a bpf program as generated by\n"
"  `nfbpf_compiler RAW <filter>`\n");
}

static const struct xt_option_entry bpf_opts[] = {
	{.name = "bytecode", .id = O_BCODE_STDIN, .type = XTTYPE_STRING},
	XTOPT_TABLEEND,
};

static void bpf_parse_string(struct xt_option_call *cb, const char *bpf_program,
			     const char separator)
{
	struct xt_bpf_info *bi = (void *) cb->data;
	const char *token;
	char sp;
	int i;

	/* parse head: length. */
	if (sscanf(bpf_program, "%hu%c", &bi->bpf_program_num_elem, &sp) != 2 ||
		   sp != separator)
		xtables_error(PARAMETER_PROBLEM,
			      "bpf: error parsing program length");
	if (!bi->bpf_program_num_elem)
		xtables_error(PARAMETER_PROBLEM,
			      "bpf: illegal zero length program");
	if (bi->bpf_program_num_elem > XT_BPF_MAX_NUM_INSTR)
		xtables_error(PARAMETER_PROBLEM,
			      "bpf: number of instructions exceeds maximum");

	/* parse instructions. */
	i = 0;
	token = bpf_program;
	while ((token = strchr(token, separator)) && (++token)[0]) {
		if (i >= bi->bpf_program_num_elem)
			xtables_error(PARAMETER_PROBLEM,
				      "bpf: real program length exceeds"
				      " the encoded length parameter");
		if (sscanf(token, "%hu %hhu %hhu %u,",
			   &bi->bpf_program[i].code,
			   &bi->bpf_program[i].jt,
			   &bi->bpf_program[i].jf,
			   &bi->bpf_program[i].k) != 4)
			xtables_error(PARAMETER_PROBLEM,
				      "bpf: error at instr %d", i);
		i++;
	}

	if (i != bi->bpf_program_num_elem)
		xtables_error(PARAMETER_PROBLEM,
			      "bpf: parsed program length is less than the"
			      " encoded length parameter");
}

static void bpf_parse(struct xt_option_call *cb)
{
	xtables_option_parse(cb);
	switch (cb->entry->id) {
	case O_BCODE_STDIN:
		bpf_parse_string(cb, cb->arg, ',');
		break;
	default:
		xtables_error(PARAMETER_PROBLEM, "bpf: unknown option");
	}
}

static void bpf_print_code(const void *ip, const struct xt_entry_match *match)
{
	const struct xt_bpf_info *info = (void *) match->data;
	int i;

	for (i = 0; i < info->bpf_program_num_elem-1; i++)
		printf("%hu %hhu %hhu %u,", info->bpf_program[i].code,
					    info->bpf_program[i].jt,
					    info->bpf_program[i].jf,
					    info->bpf_program[i].k);

	printf("%hu %hhu %hhu %u", info->bpf_program[i].code,
				    info->bpf_program[i].jt,
				    info->bpf_program[i].jf,
				    info->bpf_program[i].k);
}

static void bpf_save(const void *ip, const struct xt_entry_match *match)
{
	const struct xt_bpf_info *info = (void *) match->data;

	printf(" --bytecode \"%hu,", info->bpf_program_num_elem);
	bpf_print_code(ip, match);
	printf("\"");
}

static void bpf_fcheck(struct xt_fcheck_call *cb)
{
	if (!(cb->xflags & (1 << O_BCODE_STDIN)))
		xtables_error(PARAMETER_PROBLEM,
			      "bpf: missing --bytecode parameter");
}

static void bpf_print(const void *ip, const struct xt_entry_match *match,
		      int numeric)
{
	printf("match bpf ");
	return bpf_print_code(ip, match);
}

static struct xtables_match bpf_match = {
	.family		= NFPROTO_UNSPEC,
	.name		= "bpf",
	.version	= XTABLES_VERSION,
	.size		= XT_ALIGN(sizeof(struct xt_bpf_info)),
	.userspacesize	= XT_ALIGN(offsetof(struct xt_bpf_info, filter)),
	.help		= bpf_help,
	.print		= bpf_print,
	.save		= bpf_save,
	.x6_parse	= bpf_parse,
	.x6_fcheck	= bpf_fcheck,
	.x6_options	= bpf_opts,
};

void _init(void)
{
	xtables_register_match(&bpf_match);
}
