• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
connbytes_help(void)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 
connbytes_parse(struct xt_option_call * cb)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 
print_mode(const struct xt_connbytes_info * sinfo)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 
print_direction(const struct xt_connbytes_info * sinfo)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
connbytes_print(const void * ip,const struct xt_entry_match * match,int numeric)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 
connbytes_save(const void * ip,const struct xt_entry_match * match)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 
_init(void)164 void _init(void)
165 {
166 	xtables_register_match(&connbytes_match);
167 }
168