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 = 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 74 static 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 92 static 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 110 static void 111 connbytes_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 131 static 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 151 static 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 164 void _init(void) 165 { 166 xtables_register_match(&connbytes_match); 167 } 168