1#include <stdio.h> 2#include <string.h> 3#include <xtables.h> 4#include <linux/netfilter/xt_connbytes.h> 5 6enum { 7 O_CONNBYTES = 0, 8 O_CONNBYTES_DIR, 9 O_CONNBYTES_MODE, 10}; 11 12static void connbytes_help(void) 13{ 14 printf( 15"connbytes match options:\n" 16" [!] --connbytes from:[to]\n" 17" --connbytes-dir [original, reply, both]\n" 18" --connbytes-mode [packets, bytes, avgpkt]\n"); 19} 20 21static const struct xt_option_entry connbytes_opts[] = { 22 {.name = "connbytes", .id = O_CONNBYTES, .type = XTTYPE_UINT64RC, 23 .flags = XTOPT_MAND | XTOPT_INVERT}, 24 {.name = "connbytes-dir", .id = O_CONNBYTES_DIR, .type = XTTYPE_STRING, 25 .flags = XTOPT_MAND}, 26 {.name = "connbytes-mode", .id = O_CONNBYTES_MODE, 27 .type = XTTYPE_STRING, .flags = XTOPT_MAND}, 28 XTOPT_TABLEEND, 29}; 30 31static void connbytes_parse(struct xt_option_call *cb) 32{ 33 struct xt_connbytes_info *sinfo = cb->data; 34 unsigned long long i; 35 36 xtables_option_parse(cb); 37 switch (cb->entry->id) { 38 case O_CONNBYTES: 39 sinfo->count.from = cb->val.u64_range[0]; 40 sinfo->count.to = cb->val.u64_range[0]; 41 if (cb->nvals == 2) 42 sinfo->count.to = cb->val.u64_range[1]; 43 if (cb->invert) { 44 i = sinfo->count.from; 45 sinfo->count.from = sinfo->count.to; 46 sinfo->count.to = i; 47 } 48 break; 49 case O_CONNBYTES_DIR: 50 if (strcmp(cb->arg, "original") == 0) 51 sinfo->direction = XT_CONNBYTES_DIR_ORIGINAL; 52 else if (strcmp(cb->arg, "reply") == 0) 53 sinfo->direction = XT_CONNBYTES_DIR_REPLY; 54 else if (strcmp(cb->arg, "both") == 0) 55 sinfo->direction = XT_CONNBYTES_DIR_BOTH; 56 else 57 xtables_error(PARAMETER_PROBLEM, 58 "Unknown --connbytes-dir `%s'", cb->arg); 59 break; 60 case O_CONNBYTES_MODE: 61 if (strcmp(cb->arg, "packets") == 0) 62 sinfo->what = XT_CONNBYTES_PKTS; 63 else if (strcmp(cb->arg, "bytes") == 0) 64 sinfo->what = XT_CONNBYTES_BYTES; 65 else if (strcmp(cb->arg, "avgpkt") == 0) 66 sinfo->what = XT_CONNBYTES_AVGPKT; 67 else 68 xtables_error(PARAMETER_PROBLEM, 69 "Unknown --connbytes-mode `%s'", cb->arg); 70 break; 71 } 72} 73 74static void print_mode(const struct xt_connbytes_info *sinfo) 75{ 76 switch (sinfo->what) { 77 case XT_CONNBYTES_PKTS: 78 fputs(" packets", stdout); 79 break; 80 case XT_CONNBYTES_BYTES: 81 fputs(" bytes", stdout); 82 break; 83 case XT_CONNBYTES_AVGPKT: 84 fputs(" avgpkt", stdout); 85 break; 86 default: 87 fputs(" unknown", stdout); 88 break; 89 } 90} 91 92static void print_direction(const struct xt_connbytes_info *sinfo) 93{ 94 switch (sinfo->direction) { 95 case XT_CONNBYTES_DIR_ORIGINAL: 96 fputs(" original", stdout); 97 break; 98 case XT_CONNBYTES_DIR_REPLY: 99 fputs(" reply", stdout); 100 break; 101 case XT_CONNBYTES_DIR_BOTH: 102 fputs(" both", stdout); 103 break; 104 default: 105 fputs(" unknown", stdout); 106 break; 107 } 108} 109 110static void 111connbytes_print(const void *ip, const struct xt_entry_match *match, int numeric) 112{ 113 const struct xt_connbytes_info *sinfo = (const void *)match->data; 114 115 if (sinfo->count.from > sinfo->count.to) 116 printf(" connbytes ! %llu:%llu", 117 (unsigned long long)sinfo->count.to, 118 (unsigned long long)sinfo->count.from); 119 else 120 printf(" connbytes %llu:%llu", 121 (unsigned long long)sinfo->count.from, 122 (unsigned long long)sinfo->count.to); 123 124 fputs(" connbytes mode", stdout); 125 print_mode(sinfo); 126 127 fputs(" connbytes direction", stdout); 128 print_direction(sinfo); 129} 130 131static void connbytes_save(const void *ip, const struct xt_entry_match *match) 132{ 133 const struct xt_connbytes_info *sinfo = (const void *)match->data; 134 135 if (sinfo->count.from > sinfo->count.to) 136 printf(" ! --connbytes %llu:%llu", 137 (unsigned long long)sinfo->count.to, 138 (unsigned long long)sinfo->count.from); 139 else 140 printf(" --connbytes %llu:%llu", 141 (unsigned long long)sinfo->count.from, 142 (unsigned long long)sinfo->count.to); 143 144 fputs(" --connbytes-mode", stdout); 145 print_mode(sinfo); 146 147 fputs(" --connbytes-dir", stdout); 148 print_direction(sinfo); 149} 150 151static struct xtables_match connbytes_match = { 152 .family = NFPROTO_UNSPEC, 153 .name = "connbytes", 154 .version = XTABLES_VERSION, 155 .size = XT_ALIGN(sizeof(struct xt_connbytes_info)), 156 .userspacesize = XT_ALIGN(sizeof(struct xt_connbytes_info)), 157 .help = connbytes_help, 158 .print = connbytes_print, 159 .save = connbytes_save, 160 .x6_parse = connbytes_parse, 161 .x6_options = connbytes_opts, 162}; 163 164void _init(void) 165{ 166 xtables_register_match(&connbytes_match); 167} 168