Home | History | Annotate | Download | only in extensions
      1 /*
      2  *	"quota2" match extension for iptables
      3  *	Sam Johnston <samj [at] samj net>
      4  *	Jan Engelhardt <jengelh [at] medozas de>, 2008
      5  *
      6  *	This program is free software; you can redistribute it and/or
      7  *	modify it under the terms of the GNU General Public License; either
      8  *	version 2 of the License, or any later version, as published by the
      9  *	Free Software Foundation.
     10  */
     11 #include <getopt.h>
     12 #include <stddef.h>
     13 #include <stdio.h>
     14 #include <stdlib.h>
     15 #include <string.h>
     16 #include <xtables.h>
     17 #include <linux/netfilter/xt_quota2.h>
     18 
     19 enum {
     20 	FL_QUOTA     = 1 << 0,
     21 	FL_NAME      = 1 << 1,
     22 	FL_GROW      = 1 << 2,
     23 	FL_PACKET    = 1 << 3,
     24 	FL_NO_CHANGE = 1 << 4,
     25 };
     26 
     27 enum {
     28 	O_QUOTA     = 0,
     29 	O_NAME,
     30 	O_GROW,
     31 	O_PACKET,
     32 	O_NO_CHANGE,
     33 };
     34 
     35 
     36 static const struct xt_option_entry quota_mt2_opts[] = {
     37 	{.name = "grow", .id = O_GROW, .type = XTTYPE_NONE},
     38 	{.name = "no-change", .id = O_NO_CHANGE, .type = XTTYPE_NONE},
     39 	{.name = "name", .id = O_NAME, .type = XTTYPE_STRING,
     40 	 .flags = XTOPT_PUT, XTOPT_POINTER(struct xt_quota_mtinfo2, name)},
     41 	{.name = "quota", .id = O_QUOTA, .type = XTTYPE_UINT64,
     42 	 .flags = XTOPT_INVERT | XTOPT_PUT,
     43 	 XTOPT_POINTER(struct xt_quota_mtinfo2, quota)},
     44 	{.name = "packets", .id = O_PACKET, .type = XTTYPE_NONE},
     45 	XTOPT_TABLEEND,
     46 };
     47 
     48 static void quota_mt2_help(void)
     49 {
     50 	printf(
     51 	"quota match options:\n"
     52 	"    --grow           provide an increasing counter\n"
     53 	"    --no-change      never change counter/quota value for matching packets\n"
     54 	"    --name name      name for the file in sysfs\n"
     55 	"[!] --quota quota    initial quota (bytes or packets)\n"
     56 	"    --packets        count packets instead of bytes\n"
     57 	);
     58 }
     59 
     60 static void quota_mt2_parse(struct xt_option_call *cb)
     61 {
     62 	struct xt_quota_mtinfo2 *info = cb->data;
     63 
     64 	xtables_option_parse(cb);
     65 	switch (cb->entry->id) {
     66 	case O_GROW:
     67 		info->flags |= XT_QUOTA_GROW;
     68 		break;
     69 	case O_NO_CHANGE:
     70 		info->flags |= XT_QUOTA_NO_CHANGE;
     71 		break;
     72 	case O_NAME:
     73 		break;
     74 	case O_PACKET:
     75 		info->flags |= XT_QUOTA_PACKET;
     76 		break;
     77 	case O_QUOTA:
     78 		if (cb->invert)
     79 			info->flags |= XT_QUOTA_INVERT;
     80 		break;
     81 	}
     82 }
     83 
     84 static void
     85 quota_mt2_save(const void *ip, const struct xt_entry_match *match)
     86 {
     87 	const struct xt_quota_mtinfo2 *q = (void *)match->data;
     88 
     89 	if (q->flags & XT_QUOTA_INVERT)
     90 		printf(" !");
     91 	if (q->flags & XT_QUOTA_GROW)
     92 		printf(" --grow ");
     93 	if (q->flags & XT_QUOTA_NO_CHANGE)
     94 		printf(" --no-change ");
     95 	if (q->flags & XT_QUOTA_PACKET)
     96 		printf(" --packets ");
     97 	if (*q->name != '\0')
     98 		printf(" --name %s ", q->name);
     99 	printf(" --quota %llu ", (unsigned long long)q->quota);
    100 }
    101 
    102 static void quota_mt2_print(const void *ip, const struct xt_entry_match *match,
    103                             int numeric)
    104 {
    105 	const struct xt_quota_mtinfo2 *q = (const void *)match->data;
    106 
    107 	if (q->flags & XT_QUOTA_INVERT)
    108 		printf(" !");
    109 	if (q->flags & XT_QUOTA_GROW)
    110 		printf(" counter");
    111 	else
    112 		printf(" quota");
    113 	if (*q->name != '\0')
    114 		printf(" %s:", q->name);
    115 	printf(" %llu ", (unsigned long long)q->quota);
    116 	if (q->flags & XT_QUOTA_PACKET)
    117 		printf("packets ");
    118 	else
    119 		printf("bytes ");
    120 	if (q->flags & XT_QUOTA_NO_CHANGE)
    121 		printf("(no-change mode) ");
    122 }
    123 
    124 static struct xtables_match quota_mt2_reg = {
    125 	.family        = NFPROTO_UNSPEC,
    126 	.revision      = 3,
    127 	.name          = "quota2",
    128 	.version       = XTABLES_VERSION,
    129 	.size          = XT_ALIGN(sizeof (struct xt_quota_mtinfo2)),
    130 	.userspacesize = offsetof(struct xt_quota_mtinfo2, quota),
    131 	.help          = quota_mt2_help,
    132 	.x6_parse      = quota_mt2_parse,
    133 	.print         = quota_mt2_print,
    134 	.save          = quota_mt2_save,
    135 	.x6_options    = quota_mt2_opts,
    136 };
    137 
    138 void _init(void)
    139 {
    140 	xtables_register_match(&quota_mt2_reg);
    141 }
    142