/*
 * em_ipset.c		IPset Ematch
 *
 * (C) 2012 Florian Westphal <fw@strlen.de>
 *
 * Parts taken from iptables libxt_set.h:
 * Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
 *                         Patrick Schaaf <bof@bof.de>
 *                         Martin Josefsson <gandalf@wlug.westbo.se>
 * Copyright (C) 2003-2010 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <stdbool.h>
#include <stdio.h>
#include <errno.h>
#include <netdb.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>

#include <xtables.h>
#include <linux/netfilter/ipset/ip_set.h>

#ifndef IPSET_INVALID_ID
typedef __u16 ip_set_id_t;

enum ip_set_dim {
	IPSET_DIM_ZERO = 0,
	IPSET_DIM_ONE,
	IPSET_DIM_TWO,
	IPSET_DIM_THREE,
	IPSET_DIM_MAX = 6,
};
#endif /* IPSET_INVALID_ID */

#include <linux/netfilter/xt_set.h>
#include "m_ematch.h"

#ifndef IPSET_INVALID_ID
#define IPSET_INVALID_ID	65535
#define SO_IP_SET		83

union ip_set_name_index {
	char name[IPSET_MAXNAMELEN];
	__u16 index;
};

#define IP_SET_OP_GET_BYNAME	0x00000006	/* Get set index by name */
struct ip_set_req_get_set {
	unsigned int op;
	unsigned int version;
	union ip_set_name_index set;
};

#define IP_SET_OP_GET_BYINDEX	0x00000007	/* Get set name by index */
/* Uses ip_set_req_get_set */

#define IP_SET_OP_VERSION	0x00000100	/* Ask kernel version */
struct ip_set_req_version {
	unsigned int op;
	unsigned int version;
};
#endif /* IPSET_INVALID_ID */

extern struct ematch_util ipset_ematch_util;

static int get_version(unsigned int *version)
{
	int res, sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
	struct ip_set_req_version req_version;
	socklen_t size = sizeof(req_version);

	if (sockfd < 0) {
		fputs("Can't open socket to ipset.\n", stderr);
		return -1;
	}

	req_version.op = IP_SET_OP_VERSION;
	res = getsockopt(sockfd, SOL_IP, SO_IP_SET, &req_version, &size);
	if (res != 0) {
		perror("xt_set getsockopt");
		return -1;
	}

	*version = req_version.version;
	return sockfd;
}

static int do_getsockopt(struct ip_set_req_get_set *req)
{
	int sockfd, res;
	socklen_t size = sizeof(struct ip_set_req_get_set);

	sockfd = get_version(&req->version);
	if (sockfd < 0)
		return -1;
	res = getsockopt(sockfd, SOL_IP, SO_IP_SET, req, &size);
	if (res != 0)
		perror("Problem when communicating with ipset");
	close(sockfd);
	if (res != 0)
		return -1;

	if (size != sizeof(struct ip_set_req_get_set)) {
		fprintf(stderr,
			"Incorrect return size from kernel during ipset lookup, (want %zu, got %zu)\n",
			sizeof(struct ip_set_req_get_set), (size_t)size);
		return -1;
	}

	return res;
}

static int
get_set_byid(char *setname, unsigned int idx)
{
	struct ip_set_req_get_set req;
	int res;

	req.op = IP_SET_OP_GET_BYINDEX;
	req.set.index = idx;
	res = do_getsockopt(&req);
	if (res != 0)
		return -1;
	if (req.set.name[0] == '\0') {
		fprintf(stderr,
			"Set with index %i in kernel doesn't exist.\n", idx);
		return -1;
	}

	strncpy(setname, req.set.name, IPSET_MAXNAMELEN);
	return 0;
}

static int
get_set_byname(const char *setname, struct xt_set_info *info)
{
	struct ip_set_req_get_set req;
	int res;

	req.op = IP_SET_OP_GET_BYNAME;
	strncpy(req.set.name, setname, IPSET_MAXNAMELEN);
	req.set.name[IPSET_MAXNAMELEN - 1] = '\0';
	res = do_getsockopt(&req);
	if (res != 0)
		return -1;
	if (req.set.index == IPSET_INVALID_ID)
		return -1;
	info->index = req.set.index;
	return 0;
}

static int
parse_dirs(const char *opt_arg, struct xt_set_info *info)
{
	char *saved = strdup(opt_arg);
	char *ptr, *tmp = saved;

	if (!tmp) {
		perror("strdup");
		return -1;
	}

	while (info->dim < IPSET_DIM_MAX && tmp != NULL) {
		info->dim++;
		ptr = strsep(&tmp, ",");
		if (strncmp(ptr, "src", 3) == 0)
			info->flags |= (1 << info->dim);
		else if (strncmp(ptr, "dst", 3) != 0) {
			fputs("You must specify (the comma separated list of) 'src' or 'dst'\n", stderr);
			free(saved);
			return -1;
		}
	}

	if (tmp)
		fprintf(stderr, "Can't be more src/dst options than %u", IPSET_DIM_MAX);
	free(saved);
	return tmp ? -1 : 0;
}

static void ipset_print_usage(FILE *fd)
{
	fprintf(fd,
	    "Usage: ipset(SETNAME FLAGS)\n" \
	    "where: SETNAME:= string\n" \
	    "       FLAGS  := { FLAG[,FLAGS] }\n" \
	    "       FLAG   := { src | dst }\n" \
	    "\n" \
	    "Example: 'ipset(bulk src,dst)'\n");
}

static int ipset_parse_eopt(struct nlmsghdr *n, struct tcf_ematch_hdr *hdr,
			    struct bstr *args)
{
	struct xt_set_info set_info;
	int ret;

	memset(&set_info, 0, sizeof(set_info));

#define PARSE_ERR(CARG, FMT, ARGS...) \
	em_parse_error(EINVAL, args, CARG, &ipset_ematch_util, FMT, ##ARGS)

	if (args == NULL)
		return PARSE_ERR(args, "ipset: missing set name");

	if (args->len >= IPSET_MAXNAMELEN)
		return PARSE_ERR(args, "ipset: set name too long (max %u)", IPSET_MAXNAMELEN - 1);
	ret = get_set_byname(args->data, &set_info);
	if (ret < 0)
		return PARSE_ERR(args, "ipset: unknown set name '%s'", args->data);

	if (args->next == NULL)
		return PARSE_ERR(args, "ipset: missing set flags");

	args = bstr_next(args);
	if (parse_dirs(args->data, &set_info))
		return PARSE_ERR(args, "ipset: error parsing set flags");

	if (args->next) {
		args = bstr_next(args);
		return PARSE_ERR(args, "ipset: unknown parameter");
	}

	addraw_l(n, MAX_MSG, hdr, sizeof(*hdr));
	addraw_l(n, MAX_MSG, &set_info, sizeof(set_info));

#undef PARSE_ERR
	return 0;
}

static int ipset_print_eopt(FILE *fd, struct tcf_ematch_hdr *hdr, void *data,
			    int data_len)
{
	int i;
	char setname[IPSET_MAXNAMELEN];
	const struct xt_set_info *set_info = data;

	if (data_len != sizeof(*set_info)) {
		fprintf(stderr, "xt_set_info struct size mismatch\n");
		return -1;
	}

	if (get_set_byid(setname, set_info->index))
		return -1;
	fputs(setname, fd);
	for (i = 1; i <= set_info->dim; i++) {
		fprintf(fd, "%s%s", i == 1 ? " " : ",", set_info->flags & (1 << i) ? "src" : "dst");
	}

	return 0;
}

struct ematch_util ipset_ematch_util = {
	.kind = "ipset",
	.kind_num = TCF_EM_IPSET,
	.parse_eopt = ipset_parse_eopt,
	.print_eopt = ipset_print_eopt,
	.print_usage = ipset_print_usage
};
