/* Shared library add-on to iptables to add verify tracking support. */
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#include <iptables.h>
#include "ipt_verify.h"

/* Function which prints out usage message. */
static void
help(void)
{
	printf(
"verify v%s options:\n"
" [!] --verify-secret=secret\n"
"				match if verifies with this secret\n"
" [!] --verify-algorithm=STUPID|SHA|MD5\n"
"				Choose algorithm - only SHA is implemented\n"
"\n", NETFILTER_VERSION);
}

static struct option opts[] = {
	{ "verify-secret", 1, 0, '1' },
	{ "verify-algorithm", 1, 0, '2' },
	{0}
};

/* Initialize the match. */
static void
init(struct ipt_entry_match *m, unsigned int *nfcache)
{
	/* Can't cache this */
	*nfcache |= NFC_UNKNOWN;
}

/* Function which parses command options; returns true if it
   ate an option */
static int
parse(int c, char **argv, int invert, unsigned int *flags,
      const struct ipt_entry *entry,
      unsigned int *nfcache,
      struct ipt_entry_match **match)
{
	struct ipt_verify_info *vinfo = (struct ipt_verify_info *)(*match)->data;

	switch (c) {
	case '1':
		if (check_inverse(optarg, &invert))
			optind++;

		bzero(vinfo->secret,IPT_SIGN_MAX_SECRET_LENGTH);
		strncpy(vinfo->secret,optarg,IPT_SIGN_MAX_SECRET_LENGTH);

		if(invert)
		  vinfo->invert=1;

		vinfo->algorithm=SHA;

		*flags = 1;
		break;

	case '2':
		if(strcmp(optarg,"SHA")) 
			exit_error(PARAMETER_PROBLEM,"Only SHA is implemented -- choose another algorithm");
	default:
		return 0;
	}

	return 1;
}

/* Final check; must have specified --verify. */
static void final_check(unsigned int flags)
{
	if (!flags)
		exit_error(PARAMETER_PROBLEM, "You must specify `--verify'");
}

/* Prints out the matchinfo. */
static void
print(const struct ipt_ip *ip,
      const struct ipt_entry_match *match,
      int numeric)
{
	struct ipt_verify_info *vinfo = (struct ipt_verify_info *)match->data;

	printf("verify ");
	printf("--verify-secret %s",vinfo->secret);
}

/* Saves the matchinfo in parsable form to stdout. */
static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
{
	struct ipt_verify_info *vinfo = (struct ipt_verify_info *)match->data;

	printf("--verify-secret %s",vinfo->secret);
}

static
struct iptables_match verify
= { NULL,
    "verify",
    NETFILTER_VERSION,
    IPT_ALIGN(sizeof(struct ipt_verify_info)),
    IPT_ALIGN(sizeof(struct ipt_verify_info)),
    &help,
    &init,
    &parse,
    &final_check,
    &print,
    &save,
    opts
};

void _init(void)
{
	register_match(&verify);
}

