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