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 19enum { 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 27enum { 28 O_QUOTA = 0, 29 O_NAME, 30 O_GROW, 31 O_PACKET, 32 O_NO_CHANGE, 33}; 34 35 36static 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 48static 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 60static 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 84static void 85quota_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 102static 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 124static 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 138void _init(void) 139{ 140 xtables_register_match("a_mt2_reg); 141} 142