/*
 * 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>
#include "config.h"

#ifdef HAVE_LINUX_BPF_H
#include <linux/bpf.h>
#endif

#include <linux/magic.h>
#include <linux/unistd.h>

#define BCODE_FILE_MAX_LEN_B	1024

enum {
	O_BCODE_STDIN = 0,
	O_OBJ_PINNED = 1,
};

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

static void bpf_help_v1(void)
{
	printf(
"bpf match options:\n"
"--bytecode <program>	        : a bpf program as generated by\n"
"                                 $(nfbpf_compile RAW '<filter>')\n"
"--object-pinned <bpf object>	: a path to a pinned BPF object in bpf fs\n");
}

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

static const struct xt_option_entry bpf_opts_v1[] = {
	{.name = "bytecode", .id = O_BCODE_STDIN, .type = XTTYPE_STRING},
	{.name = "object-pinned" , .id = O_OBJ_PINNED, .type = XTTYPE_STRING,
	 .flags = XTOPT_PUT, XTOPT_POINTER(struct xt_bpf_info_v1, path)},
	XTOPT_TABLEEND,
};

static int bpf_obj_get_readonly(const char *filepath)
{
#if defined HAVE_LINUX_BPF_H && defined __NR_bpf && defined BPF_FS_MAGIC
	/* union bpf_attr includes this in an anonymous struct, but the
	 * file_flags field and the BPF_F_RDONLY constant are only present
	 * in Linux 4.15+ kernel headers (include/uapi/linux/bpf.h)
	 */
	struct {   // this part of union bpf_attr is for BPF_OBJ_* commands
		__aligned_u64	pathname;
		__u32		bpf_fd;
		__u32		file_flags;
	} attr = {
		.pathname = (__u64)filepath,
		.file_flags = (1U << 3),   // BPF_F_RDONLY
	};
	int fd = syscall(__NR_bpf, BPF_OBJ_GET, &attr, sizeof(attr));
	if (fd >= 0) return fd;

	/* on any error fallback to default R/W access for pre-4.15-rc1 kernels */
	attr.file_flags = 0;
	return syscall(__NR_bpf, BPF_OBJ_GET, &attr, sizeof(attr));
#else
	xtables_error(OTHER_PROBLEM,
		      "No bpf header, kernel headers too old?\n");
	return -EINVAL;
#endif
}

static void bpf_parse_string(struct sock_filter *pc, __u16 *lenp, __u16 len_max,
			     const char *bpf_program)
{
	const char separator = ',';
	const char *token;
	char sp;
	int i;
	__u16 len;

	/* parse head: length. */
	if (sscanf(bpf_program, "%hu%c", &len, &sp) != 2 ||
		   sp != separator)
		xtables_error(PARAMETER_PROBLEM,
			      "bpf: error parsing program length");
	if (!len)
		xtables_error(PARAMETER_PROBLEM,
			      "bpf: illegal zero length program");
	if (len > len_max)
		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 >= len)
			xtables_error(PARAMETER_PROBLEM,
				      "bpf: real program length exceeds"
				      " the encoded length parameter");
		if (sscanf(token, "%hu %hhu %hhu %u,",
			   &pc->code, &pc->jt, &pc->jf, &pc->k) != 4)
			xtables_error(PARAMETER_PROBLEM,
				      "bpf: error at instr %d", i);
		i++;
		pc++;
	}

	if (i != len)
		xtables_error(PARAMETER_PROBLEM,
			      "bpf: parsed program length is less than the"
			      " encoded length parameter");

	*lenp = len;
}

static void bpf_parse_obj_pinned(struct xt_bpf_info_v1 *bi,
				 const char *filepath)
{
	bi->fd = bpf_obj_get_readonly(filepath);
	if (bi->fd < 0)
		xtables_error(PARAMETER_PROBLEM,
			      "bpf: failed to get bpf object");

	/* Cannot close bi->fd explicitly. Rely on exit */
	if (fcntl(bi->fd, F_SETFD, FD_CLOEXEC) == -1) {
		xtables_error(OTHER_PROBLEM,
			      "Could not set close on exec: %s\n",
			      strerror(errno));
	}
}

static void bpf_parse(struct xt_option_call *cb)
{
	struct xt_bpf_info *bi = (void *) cb->data;

	xtables_option_parse(cb);
	switch (cb->entry->id) {
	case O_BCODE_STDIN:
		bpf_parse_string(bi->bpf_program, &bi->bpf_program_num_elem,
				 ARRAY_SIZE(bi->bpf_program), cb->arg);
		break;
	default:
		xtables_error(PARAMETER_PROBLEM, "bpf: unknown option");
	}
}

static void bpf_parse_v1(struct xt_option_call *cb)
{
	struct xt_bpf_info_v1 *bi = (void *) cb->data;

	xtables_option_parse(cb);
	switch (cb->entry->id) {
	case O_BCODE_STDIN:
		bpf_parse_string(bi->bpf_program, &bi->bpf_program_num_elem,
				 ARRAY_SIZE(bi->bpf_program), cb->arg);
		bi->mode = XT_BPF_MODE_BYTECODE;
		break;
	case O_OBJ_PINNED:
		bpf_parse_obj_pinned(bi, cb->arg);
		bi->mode = XT_BPF_MODE_FD_PINNED;
		break;
	default:
		xtables_error(PARAMETER_PROBLEM, "bpf: unknown option");
	}
}

static void bpf_print_code(const struct sock_filter *pc, __u16 len, char tail)
{
	for (; len; len--, pc++)
		printf("%hu %hhu %hhu %u%c",
		       pc->code, pc->jt, pc->jf, pc->k,
		       len > 1 ? ',' : tail);
}

static void bpf_save_code(const struct sock_filter *pc, __u16 len)
{
	printf(" --bytecode \"%hu,", len);
	bpf_print_code(pc, len, '\"');
}

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

	bpf_save_code(info->bpf_program, info->bpf_program_num_elem);
}

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

	if (info->mode == XT_BPF_MODE_BYTECODE)
		bpf_save_code(info->bpf_program, info->bpf_program_num_elem);
	else if (info->mode == XT_BPF_MODE_FD_PINNED)
		printf(" --object-pinned %s", info->path);
	else
		xtables_error(OTHER_PROBLEM, "unknown bpf mode");
}

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_fcheck_v1(struct xt_fcheck_call *cb)
{
	const unsigned int bit_bcode = 1 << O_BCODE_STDIN;
	const unsigned int bit_pinned = 1 << O_OBJ_PINNED;
	unsigned int flags;

	flags = cb->xflags & (bit_bcode | bit_pinned);
	if (flags != bit_bcode && flags != bit_pinned)
		xtables_error(PARAMETER_PROBLEM,
			      "bpf: one of --bytecode or --pinned is required");
}

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

	printf("match bpf ");
	bpf_print_code(info->bpf_program, info->bpf_program_num_elem, '\0');
}

static void bpf_print_v1(const void *ip, const struct xt_entry_match *match,
			 int numeric)
{
	const struct xt_bpf_info_v1 *info = (void *) match->data;

	printf("match bpf ");
	if (info->mode == XT_BPF_MODE_BYTECODE)
		bpf_print_code(info->bpf_program, info->bpf_program_num_elem, '\0');
	else if (info->mode == XT_BPF_MODE_FD_PINNED)
		printf("pinned %s", info->path);
	else
		printf("unknown");
}

static struct xtables_match bpf_matches[] = {
	{
		.family		= NFPROTO_UNSPEC,
		.name		= "bpf",
		.version	= XTABLES_VERSION,
		.revision	= 0,
		.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,
	},
	{
		.family		= NFPROTO_UNSPEC,
		.name		= "bpf",
		.version	= XTABLES_VERSION,
		.revision	= 1,
		.size		= XT_ALIGN(sizeof(struct xt_bpf_info_v1)),
		.userspacesize	= XT_ALIGN(offsetof(struct xt_bpf_info_v1, filter)),
		.help		= bpf_help_v1,
		.print		= bpf_print_v1,
		.save		= bpf_save_v1,
		.x6_parse	= bpf_parse_v1,
		.x6_fcheck	= bpf_fcheck_v1,
		.x6_options	= bpf_opts_v1,
	},
};

void _init(void)
{
	xtables_register_matches(bpf_matches, ARRAY_SIZE(bpf_matches));
}
