15caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall/*
25caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall *	"quota2" match extension for iptables
35caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall *	Sam Johnston <samj [at] samj net>
45caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall *	Jan Engelhardt <jengelh [at] medozas de>, 2008
55caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall *
65caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall *	This program is free software; you can redistribute it and/or
75caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall *	modify it under the terms of the GNU General Public License; either
85caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall *	version 2 of the License, or any later version, as published by the
95caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall *	Free Software Foundation.
105caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall */
115caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall#include <getopt.h>
125caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall#include <stddef.h>
135caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall#include <stdio.h>
145caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall#include <stdlib.h>
155caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall#include <string.h>
165caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall#include <xtables.h>
1736574090407b87fbb72c752698c805ef87046ae8JP Abgrall#include <linux/netfilter/xt_quota2.h>
185caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall
195caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrallenum {
205caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	FL_QUOTA     = 1 << 0,
215caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	FL_NAME      = 1 << 1,
225caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	FL_GROW      = 1 << 2,
235caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	FL_PACKET    = 1 << 3,
245caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	FL_NO_CHANGE = 1 << 4,
255caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall};
265caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall
2736574090407b87fbb72c752698c805ef87046ae8JP Abgrallenum {
2836574090407b87fbb72c752698c805ef87046ae8JP Abgrall	O_QUOTA     = 0,
2936574090407b87fbb72c752698c805ef87046ae8JP Abgrall	O_NAME,
3036574090407b87fbb72c752698c805ef87046ae8JP Abgrall	O_GROW,
3136574090407b87fbb72c752698c805ef87046ae8JP Abgrall	O_PACKET,
3236574090407b87fbb72c752698c805ef87046ae8JP Abgrall	O_NO_CHANGE,
3336574090407b87fbb72c752698c805ef87046ae8JP Abgrall};
3436574090407b87fbb72c752698c805ef87046ae8JP Abgrall
3536574090407b87fbb72c752698c805ef87046ae8JP Abgrall
3636574090407b87fbb72c752698c805ef87046ae8JP Abgrallstatic const struct xt_option_entry quota_mt2_opts[] = {
3736574090407b87fbb72c752698c805ef87046ae8JP Abgrall	{.name = "grow", .id = O_GROW, .type = XTTYPE_NONE},
3836574090407b87fbb72c752698c805ef87046ae8JP Abgrall	{.name = "no-change", .id = O_NO_CHANGE, .type = XTTYPE_NONE},
3936574090407b87fbb72c752698c805ef87046ae8JP Abgrall	{.name = "name", .id = O_NAME, .type = XTTYPE_STRING,
4036574090407b87fbb72c752698c805ef87046ae8JP Abgrall	 .flags = XTOPT_PUT, XTOPT_POINTER(struct xt_quota_mtinfo2, name)},
4136574090407b87fbb72c752698c805ef87046ae8JP Abgrall	{.name = "quota", .id = O_QUOTA, .type = XTTYPE_UINT64,
4236574090407b87fbb72c752698c805ef87046ae8JP Abgrall	 .flags = XTOPT_INVERT | XTOPT_PUT,
4336574090407b87fbb72c752698c805ef87046ae8JP Abgrall	 XTOPT_POINTER(struct xt_quota_mtinfo2, quota)},
4436574090407b87fbb72c752698c805ef87046ae8JP Abgrall	{.name = "packets", .id = O_PACKET, .type = XTTYPE_NONE},
4536574090407b87fbb72c752698c805ef87046ae8JP Abgrall	XTOPT_TABLEEND,
465caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall};
475caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall
485caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrallstatic void quota_mt2_help(void)
495caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall{
505caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	printf(
515caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	"quota match options:\n"
525caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	"    --grow           provide an increasing counter\n"
535caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	"    --no-change      never change counter/quota value for matching packets\n"
545caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	"    --name name      name for the file in sysfs\n"
555caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	"[!] --quota quota    initial quota (bytes or packets)\n"
565caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	"    --packets        count packets instead of bytes\n"
575caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	);
585caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall}
595caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall
6036574090407b87fbb72c752698c805ef87046ae8JP Abgrallstatic void quota_mt2_parse(struct xt_option_call *cb)
615caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall{
6236574090407b87fbb72c752698c805ef87046ae8JP Abgrall	struct xt_quota_mtinfo2 *info = cb->data;
635caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall
6436574090407b87fbb72c752698c805ef87046ae8JP Abgrall	xtables_option_parse(cb);
6536574090407b87fbb72c752698c805ef87046ae8JP Abgrall	switch (cb->entry->id) {
6636574090407b87fbb72c752698c805ef87046ae8JP Abgrall	case O_GROW:
675caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall		info->flags |= XT_QUOTA_GROW;
6836574090407b87fbb72c752698c805ef87046ae8JP Abgrall		break;
6936574090407b87fbb72c752698c805ef87046ae8JP Abgrall	case O_NO_CHANGE:
705caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall		info->flags |= XT_QUOTA_NO_CHANGE;
7136574090407b87fbb72c752698c805ef87046ae8JP Abgrall		break;
7236574090407b87fbb72c752698c805ef87046ae8JP Abgrall	case O_NAME:
7336574090407b87fbb72c752698c805ef87046ae8JP Abgrall		break;
7436574090407b87fbb72c752698c805ef87046ae8JP Abgrall	case O_PACKET:
755caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall		info->flags |= XT_QUOTA_PACKET;
7636574090407b87fbb72c752698c805ef87046ae8JP Abgrall		break;
7736574090407b87fbb72c752698c805ef87046ae8JP Abgrall	case O_QUOTA:
7892556c7047257284cc8659c769b800219cff47a5JP Abgrall		if (cb->invert)
7992556c7047257284cc8659c769b800219cff47a5JP Abgrall			info->flags |= XT_QUOTA_INVERT;
8036574090407b87fbb72c752698c805ef87046ae8JP Abgrall		break;
815caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	}
825caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall}
835caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall
845caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrallstatic void
855caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrallquota_mt2_save(const void *ip, const struct xt_entry_match *match)
865caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall{
875caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	const struct xt_quota_mtinfo2 *q = (void *)match->data;
885caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall
895caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	if (q->flags & XT_QUOTA_INVERT)
905caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall		printf(" !");
915caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	if (q->flags & XT_QUOTA_GROW)
925caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall		printf(" --grow ");
935caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	if (q->flags & XT_QUOTA_NO_CHANGE)
945caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall		printf(" --no-change ");
955caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	if (q->flags & XT_QUOTA_PACKET)
965caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall		printf(" --packets ");
975caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	if (*q->name != '\0')
985caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall		printf(" --name %s ", q->name);
995caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	printf(" --quota %llu ", (unsigned long long)q->quota);
1005caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall}
1015caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall
1025caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrallstatic void quota_mt2_print(const void *ip, const struct xt_entry_match *match,
1035caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall                            int numeric)
1045caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall{
1055caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	const struct xt_quota_mtinfo2 *q = (const void *)match->data;
1065caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall
1075caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	if (q->flags & XT_QUOTA_INVERT)
1085caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall		printf(" !");
1095caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	if (q->flags & XT_QUOTA_GROW)
1105caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall		printf(" counter");
1115caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	else
1125caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall		printf(" quota");
1135caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	if (*q->name != '\0')
1145caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall		printf(" %s:", q->name);
1155caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	printf(" %llu ", (unsigned long long)q->quota);
1165caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	if (q->flags & XT_QUOTA_PACKET)
1175caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall		printf("packets ");
1185caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	else
1195caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall		printf("bytes ");
1205caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	if (q->flags & XT_QUOTA_NO_CHANGE)
1215caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall		printf("(no-change mode) ");
1225caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall}
1235caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall
1245caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrallstatic struct xtables_match quota_mt2_reg = {
1255caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	.family        = NFPROTO_UNSPEC,
1265caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	.revision      = 3,
1275caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	.name          = "quota2",
1285caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	.version       = XTABLES_VERSION,
1295caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	.size          = XT_ALIGN(sizeof (struct xt_quota_mtinfo2)),
1305caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	.userspacesize = offsetof(struct xt_quota_mtinfo2, quota),
1315caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	.help          = quota_mt2_help,
13236574090407b87fbb72c752698c805ef87046ae8JP Abgrall	.x6_parse      = quota_mt2_parse,
1335caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	.print         = quota_mt2_print,
1345caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	.save          = quota_mt2_save,
13536574090407b87fbb72c752698c805ef87046ae8JP Abgrall	.x6_options    = quota_mt2_opts,
1365caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall};
1375caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall
13836574090407b87fbb72c752698c805ef87046ae8JP Abgrallvoid _init(void)
1395caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall{
1405caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall	xtables_register_match(&quota_mt2_reg);
1415caed2aebebf7c72dfa982f247ac35ec67a1b852JP Abgrall}
142