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 = UINT64_MAX; 41 if (cb->nvals == 2) 42 sinfo->count.to = cb->val.u64_range[1]; 43 44 if (sinfo->count.to < sinfo->count.from) 45 xtables_error(PARAMETER_PROBLEM, "%llu should be less than %llu", 46 (unsigned long long)sinfo->count.from, 47 (unsigned long long)sinfo->count.to); 48 if (cb->invert) { 49 i = sinfo->count.from; 50 sinfo->count.from = sinfo->count.to; 51 sinfo->count.to = i; 52 } 53 break; 54 case O_CONNBYTES_DIR: 55 if (strcmp(cb->arg, "original") == 0) 56 sinfo->direction = XT_CONNBYTES_DIR_ORIGINAL; 57 else if (strcmp(cb->arg, "reply") == 0) 58 sinfo->direction = XT_CONNBYTES_DIR_REPLY; 59 else if (strcmp(cb->arg, "both") == 0) 60 sinfo->direction = XT_CONNBYTES_DIR_BOTH; 61 else 62 xtables_error(PARAMETER_PROBLEM, 63 "Unknown --connbytes-dir `%s'", cb->arg); 64 break; 65 case O_CONNBYTES_MODE: 66 if (strcmp(cb->arg, "packets") == 0) 67 sinfo->what = XT_CONNBYTES_PKTS; 68 else if (strcmp(cb->arg, "bytes") == 0) 69 sinfo->what = XT_CONNBYTES_BYTES; 70 else if (strcmp(cb->arg, "avgpkt") == 0) 71 sinfo->what = XT_CONNBYTES_AVGPKT; 72 else 73 xtables_error(PARAMETER_PROBLEM, 74 "Unknown --connbytes-mode `%s'", cb->arg); 75 break; 76 } 77} 78 79static void print_mode(const struct xt_connbytes_info *sinfo) 80{ 81 switch (sinfo->what) { 82 case XT_CONNBYTES_PKTS: 83 fputs(" packets", stdout); 84 break; 85 case XT_CONNBYTES_BYTES: 86 fputs(" bytes", stdout); 87 break; 88 case XT_CONNBYTES_AVGPKT: 89 fputs(" avgpkt", stdout); 90 break; 91 default: 92 fputs(" unknown", stdout); 93 break; 94 } 95} 96 97static void print_direction(const struct xt_connbytes_info *sinfo) 98{ 99 switch (sinfo->direction) { 100 case XT_CONNBYTES_DIR_ORIGINAL: 101 fputs(" original", stdout); 102 break; 103 case XT_CONNBYTES_DIR_REPLY: 104 fputs(" reply", stdout); 105 break; 106 case XT_CONNBYTES_DIR_BOTH: 107 fputs(" both", stdout); 108 break; 109 default: 110 fputs(" unknown", stdout); 111 break; 112 } 113} 114 115static void print_from_to(const struct xt_connbytes_info *sinfo, const char *prefix) 116{ 117 unsigned long long from, to; 118 119 if (sinfo->count.from > sinfo->count.to) { 120 fputs(" !", stdout); 121 from = sinfo->count.to; 122 to = sinfo->count.from; 123 } else { 124 to = sinfo->count.to; 125 from = sinfo->count.from; 126 } 127 printf(" %sconnbytes %llu", prefix, from); 128 if (to && to < UINT64_MAX) 129 printf(":%llu", to); 130} 131 132static void 133connbytes_print(const void *ip, const struct xt_entry_match *match, int numeric) 134{ 135 const struct xt_connbytes_info *sinfo = (const void *)match->data; 136 137 print_from_to(sinfo, ""); 138 139 fputs(" connbytes mode", stdout); 140 print_mode(sinfo); 141 142 fputs(" connbytes direction", stdout); 143 print_direction(sinfo); 144} 145 146static void connbytes_save(const void *ip, const struct xt_entry_match *match) 147{ 148 const struct xt_connbytes_info *sinfo = (const void *)match->data; 149 150 print_from_to(sinfo, "--"); 151 152 fputs(" --connbytes-mode", stdout); 153 print_mode(sinfo); 154 155 fputs(" --connbytes-dir", stdout); 156 print_direction(sinfo); 157} 158 159static struct xtables_match connbytes_match = { 160 .family = NFPROTO_UNSPEC, 161 .name = "connbytes", 162 .version = XTABLES_VERSION, 163 .size = XT_ALIGN(sizeof(struct xt_connbytes_info)), 164 .userspacesize = XT_ALIGN(sizeof(struct xt_connbytes_info)), 165 .help = connbytes_help, 166 .print = connbytes_print, 167 .save = connbytes_save, 168 .x6_parse = connbytes_parse, 169 .x6_options = connbytes_opts, 170}; 171 172void _init(void) 173{ 174 xtables_register_match(&connbytes_match); 175} 176