1 #include <stdio.h> 2 #include <string.h> 3 #include <xtables.h> 4 #include <linux/netfilter/xt_connbytes.h> 5 6 enum { 7 O_CONNBYTES = 0, 8 O_CONNBYTES_DIR, 9 O_CONNBYTES_MODE, 10 }; 11 12 static 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 21 static 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 31 static 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 79 static 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 97 static 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 115 static 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 132 static void 133 connbytes_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 146 static 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 159 static 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 172 void _init(void) 173 { 174 xtables_register_match(&connbytes_match); 175 } 176