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   = 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