libxt_connbytes.c revision bbe83862a5e1baf15f7c923352d4afdf59bc70e2
1/* Shared library add-on to iptables to add byte tracking support. */ 2#include <stdio.h> 3#include <netdb.h> 4#include <string.h> 5#include <stdlib.h> 6#include <getopt.h> 7#include <xtables.h> 8#include <linux/netfilter/nf_conntrack_common.h> 9#include <linux/netfilter/xt_connbytes.h> 10 11static void connbytes_help(void) 12{ 13 printf( 14"connbytes match options:\n" 15" [!] --connbytes from:[to]\n" 16" --connbytes-dir [original, reply, both]\n" 17" --connbytes-mode [packets, bytes, avgpkt]\n"); 18} 19 20static const struct option connbytes_opts[] = { 21 { "connbytes", 1, NULL, '1' }, 22 { "connbytes-dir", 1, NULL, '2' }, 23 { "connbytes-mode", 1, NULL, '3' }, 24 { .name = NULL } 25}; 26 27static void 28parse_range(const char *arg, struct xt_connbytes_info *si) 29{ 30 char *colon,*p; 31 32 si->count.from = strtoul(arg,&colon,10); 33 if (*colon != ':') 34 xtables_error(PARAMETER_PROBLEM, "Bad range \"%s\"", arg); 35 si->count.to = strtoul(colon+1,&p,10); 36 if (p == colon+1) { 37 /* second number omited */ 38 si->count.to = 0xffffffff; 39 } 40 if (si->count.from > si->count.to) 41 xtables_error(PARAMETER_PROBLEM, "%llu should be less than %llu", 42 (unsigned long long)si->count.from, 43 (unsigned long long)si->count.to); 44} 45 46static int 47connbytes_parse(int c, char **argv, int invert, unsigned int *flags, 48 const void *entry, struct xt_entry_match **match) 49{ 50 struct xt_connbytes_info *sinfo = (struct xt_connbytes_info *)(*match)->data; 51 unsigned long i; 52 53 switch (c) { 54 case '1': 55 if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) 56 optind++; 57 58 parse_range(optarg, sinfo); 59 if (invert) { 60 i = sinfo->count.from; 61 sinfo->count.from = sinfo->count.to; 62 sinfo->count.to = i; 63 } 64 *flags |= 1; 65 break; 66 case '2': 67 if (!strcmp(optarg, "original")) 68 sinfo->direction = XT_CONNBYTES_DIR_ORIGINAL; 69 else if (!strcmp(optarg, "reply")) 70 sinfo->direction = XT_CONNBYTES_DIR_REPLY; 71 else if (!strcmp(optarg, "both")) 72 sinfo->direction = XT_CONNBYTES_DIR_BOTH; 73 else 74 xtables_error(PARAMETER_PROBLEM, 75 "Unknown --connbytes-dir `%s'", optarg); 76 77 *flags |= 2; 78 break; 79 case '3': 80 if (!strcmp(optarg, "packets")) 81 sinfo->what = XT_CONNBYTES_PKTS; 82 else if (!strcmp(optarg, "bytes")) 83 sinfo->what = XT_CONNBYTES_BYTES; 84 else if (!strcmp(optarg, "avgpkt")) 85 sinfo->what = XT_CONNBYTES_AVGPKT; 86 else 87 xtables_error(PARAMETER_PROBLEM, 88 "Unknown --connbytes-mode `%s'", optarg); 89 *flags |= 4; 90 break; 91 default: 92 return 0; 93 } 94 95 return 1; 96} 97 98static void connbytes_check(unsigned int flags) 99{ 100 if (flags != 7) 101 xtables_error(PARAMETER_PROBLEM, "You must specify `--connbytes'" 102 "`--connbytes-dir' and `--connbytes-mode'"); 103} 104 105static void print_mode(const struct xt_connbytes_info *sinfo) 106{ 107 switch (sinfo->what) { 108 case XT_CONNBYTES_PKTS: 109 fputs("packets ", stdout); 110 break; 111 case XT_CONNBYTES_BYTES: 112 fputs("bytes ", stdout); 113 break; 114 case XT_CONNBYTES_AVGPKT: 115 fputs("avgpkt ", stdout); 116 break; 117 default: 118 fputs("unknown ", stdout); 119 break; 120 } 121} 122 123static void print_direction(const struct xt_connbytes_info *sinfo) 124{ 125 switch (sinfo->direction) { 126 case XT_CONNBYTES_DIR_ORIGINAL: 127 fputs("original ", stdout); 128 break; 129 case XT_CONNBYTES_DIR_REPLY: 130 fputs("reply ", stdout); 131 break; 132 case XT_CONNBYTES_DIR_BOTH: 133 fputs("both ", stdout); 134 break; 135 default: 136 fputs("unknown ", stdout); 137 break; 138 } 139} 140 141static void 142connbytes_print(const void *ip, const struct xt_entry_match *match, int numeric) 143{ 144 const struct xt_connbytes_info *sinfo = (const void *)match->data; 145 146 if (sinfo->count.from > sinfo->count.to) 147 printf("connbytes ! %llu:%llu ", 148 (unsigned long long)sinfo->count.to, 149 (unsigned long long)sinfo->count.from); 150 else 151 printf("connbytes %llu:%llu ", 152 (unsigned long long)sinfo->count.from, 153 (unsigned long long)sinfo->count.to); 154 155 fputs("connbytes mode ", stdout); 156 print_mode(sinfo); 157 158 fputs("connbytes direction ", stdout); 159 print_direction(sinfo); 160} 161 162static void connbytes_save(const void *ip, const struct xt_entry_match *match) 163{ 164 const struct xt_connbytes_info *sinfo = (const void *)match->data; 165 166 if (sinfo->count.from > sinfo->count.to) 167 printf("! --connbytes %llu:%llu ", 168 (unsigned long long)sinfo->count.to, 169 (unsigned long long)sinfo->count.from); 170 else 171 printf("--connbytes %llu:%llu ", 172 (unsigned long long)sinfo->count.from, 173 (unsigned long long)sinfo->count.to); 174 175 fputs("--connbytes-mode ", stdout); 176 print_mode(sinfo); 177 178 fputs("--connbytes-dir ", stdout); 179 print_direction(sinfo); 180} 181 182static struct xtables_match connbytes_match = { 183 .family = NFPROTO_UNSPEC, 184 .name = "connbytes", 185 .version = XTABLES_VERSION, 186 .size = XT_ALIGN(sizeof(struct xt_connbytes_info)), 187 .userspacesize = XT_ALIGN(sizeof(struct xt_connbytes_info)), 188 .help = connbytes_help, 189 .parse = connbytes_parse, 190 .final_check = connbytes_check, 191 .print = connbytes_print, 192 .save = connbytes_save, 193 .extra_opts = connbytes_opts, 194}; 195 196void _init(void) 197{ 198 xtables_register_match(&connbytes_match); 199} 200