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("a_mt2_reg); 141 } 142