Home | History | Annotate | Download | only in extensions
      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