1/*
2
3	bcount match (experimental)
4	Copyright (C) 2006 Jonathan Zarate
5
6	Licensed under GNU GPL v2 or later.
7
8*/
9#include <stdio.h>
10#include <string.h>
11#include <stdlib.h>
12#include <getopt.h>
13
14#include <iptables.h>
15#include <linux/netfilter_ipv4/ipt_bcount.h>
16
17
18#undef IPTABLES_SAVE
19
20
21static void help(void)
22{
23	printf(
24		"bcount match v0.00\n"
25		"[!] --range min:max (upper range of 0x0FFFFFFF or more means unlimited)\n"
26	);
27}
28
29static void init(struct ipt_entry_match *match, unsigned int *nfcache)
30{
31	struct ipt_bcount_match *info = (struct ipt_bcount_match *)match->data;
32	info->min = 0xFFFFFFFF;
33	info->max = 0x0FFFFFFF;
34	*nfcache |= NFC_UNKNOWN;
35}
36
37static struct option opts[] = {
38	{ .name = "range",	.has_arg = 1, .flag = 0, .val = '1' },
39	{ .name = NULL }
40};
41
42static int parse(int c, char **argv, int invert, unsigned int *flags,
43				 const struct ipt_entry *entry, unsigned int *nfcache,
44				 struct ipt_entry_match **match)
45{
46	char *p;
47	struct ipt_bcount_match *info;
48
49	if (c != '1') return 0;
50
51	info = (struct ipt_bcount_match *)(*match)->data;
52
53	*flags = 1;
54	check_inverse(optarg, &invert, &optind, 0);
55	if (invert) info->invert = 1;
56
57	info->min = strtoul(argv[optind - 1], &p, 0);
58	if (*p == '+') {
59		++p;
60	}
61	else if ((*p == '-') || (*p == ':')) {
62		++p;
63		if ((*p == 0) || (strcmp(p, "max") == 0)) {
64			info->max = 0x0FFFFFFF;
65		}
66		else {
67			info->max = strtoul(p, &p, 0);
68			if (info->max > 0x0FFFFFFF) info->max = 0x0FFFFFFF;
69		}
70	}
71
72	if ((*p != 0) || (info->min > info->max))
73		exit_error(PARAMETER_PROBLEM, "Invalid range");
74	return 1;
75}
76
77static void final_check(unsigned int flags)
78{
79	if (!flags) {
80		exit_error(PARAMETER_PROBLEM, "Invalid range");
81	}
82}
83
84static void print_match(const struct ipt_bcount_match *info)
85{
86	if (info->min != 0xFFFFFFFF) {
87		if (info->invert) printf("! ");
88		printf("--range %u", info->min);
89		if (info->max == 0x0FFFFFFF) printf("+ ");
90			else printf(":%u ", info->max);
91	}
92}
93
94static void print(const struct ipt_ip *ip, const struct ipt_entry_match *match, int numeric)
95{
96	printf("bcount ");
97	print_match((const struct ipt_bcount_match *)match->data);
98}
99
100static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
101{
102#ifdef IPTABLES_SAVE
103	print_match((const struct ipt_bcount_match *)match->data);
104#endif
105}
106
107
108static struct iptables_match bcount_match = {
109	.name          = "bcount",
110	.version       = IPTABLES_VERSION,
111	.size          = IPT_ALIGN(sizeof(struct ipt_bcount_match)),
112	.userspacesize = IPT_ALIGN(sizeof(struct ipt_bcount_match)),
113	.help          = &help,
114	.init          = &init,
115	.parse         = &parse,
116	.final_check   = &final_check,
117	.print         = &print,
118	.save          = &save,
119	.extra_opts    = opts
120};
121
122void _init(void)
123{
124	register_match(&bcount_match);
125}
126