• 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   = UINT64_MAX;
41 		if (cb->nvals == 2)
42 			sinfo->count.to = cb->val.u64_range[1];
43 
44 		if (cb->invert) {
45 			i = sinfo->count.from;
46 			sinfo->count.from = sinfo->count.to;
47 			sinfo->count.to = i;
48 		}
49 		break;
50 	case O_CONNBYTES_DIR:
51 		if (strcmp(cb->arg, "original") == 0)
52 			sinfo->direction = XT_CONNBYTES_DIR_ORIGINAL;
53 		else if (strcmp(cb->arg, "reply") == 0)
54 			sinfo->direction = XT_CONNBYTES_DIR_REPLY;
55 		else if (strcmp(cb->arg, "both") == 0)
56 			sinfo->direction = XT_CONNBYTES_DIR_BOTH;
57 		else
58 			xtables_error(PARAMETER_PROBLEM,
59 				   "Unknown --connbytes-dir `%s'", cb->arg);
60 		break;
61 	case O_CONNBYTES_MODE:
62 		if (strcmp(cb->arg, "packets") == 0)
63 			sinfo->what = XT_CONNBYTES_PKTS;
64 		else if (strcmp(cb->arg, "bytes") == 0)
65 			sinfo->what = XT_CONNBYTES_BYTES;
66 		else if (strcmp(cb->arg, "avgpkt") == 0)
67 			sinfo->what = XT_CONNBYTES_AVGPKT;
68 		else
69 			xtables_error(PARAMETER_PROBLEM,
70 				   "Unknown --connbytes-mode `%s'", cb->arg);
71 		break;
72 	}
73 }
74 
print_mode(const struct xt_connbytes_info * sinfo)75 static void print_mode(const struct xt_connbytes_info *sinfo)
76 {
77 	switch (sinfo->what) {
78 		case XT_CONNBYTES_PKTS:
79 			fputs(" packets", stdout);
80 			break;
81 		case XT_CONNBYTES_BYTES:
82 			fputs(" bytes", stdout);
83 			break;
84 		case XT_CONNBYTES_AVGPKT:
85 			fputs(" avgpkt", stdout);
86 			break;
87 		default:
88 			fputs(" unknown", stdout);
89 			break;
90 	}
91 }
92 
print_direction(const struct xt_connbytes_info * sinfo)93 static void print_direction(const struct xt_connbytes_info *sinfo)
94 {
95 	switch (sinfo->direction) {
96 		case XT_CONNBYTES_DIR_ORIGINAL:
97 			fputs(" original", stdout);
98 			break;
99 		case XT_CONNBYTES_DIR_REPLY:
100 			fputs(" reply", stdout);
101 			break;
102 		case XT_CONNBYTES_DIR_BOTH:
103 			fputs(" both", stdout);
104 			break;
105 		default:
106 			fputs(" unknown", stdout);
107 			break;
108 	}
109 }
110 
print_from_to(const struct xt_connbytes_info * sinfo,const char * prefix)111 static void print_from_to(const struct xt_connbytes_info *sinfo, const char *prefix)
112 {
113 	unsigned long long from, to;
114 
115 	if (sinfo->count.from > sinfo->count.to) {
116 		fputs(" !", stdout);
117 		from = sinfo->count.to;
118 		to = sinfo->count.from;
119 	} else {
120 		to = sinfo->count.to;
121 		from = sinfo->count.from;
122 	}
123 	printf(" %sconnbytes %llu", prefix, from);
124 	if (to && to < UINT64_MAX)
125 		printf(":%llu", to);
126 }
127 
128 static void
connbytes_print(const void * ip,const struct xt_entry_match * match,int numeric)129 connbytes_print(const void *ip, const struct xt_entry_match *match, int numeric)
130 {
131 	const struct xt_connbytes_info *sinfo = (const void *)match->data;
132 
133 	print_from_to(sinfo, "");
134 
135 	fputs(" connbytes mode", stdout);
136 	print_mode(sinfo);
137 
138 	fputs(" connbytes direction", stdout);
139 	print_direction(sinfo);
140 }
141 
connbytes_save(const void * ip,const struct xt_entry_match * match)142 static void connbytes_save(const void *ip, const struct xt_entry_match *match)
143 {
144 	const struct xt_connbytes_info *sinfo = (const void *)match->data;
145 
146 	print_from_to(sinfo, "--");
147 
148 	fputs(" --connbytes-mode", stdout);
149 	print_mode(sinfo);
150 
151 	fputs(" --connbytes-dir", stdout);
152 	print_direction(sinfo);
153 }
154 
155 
connbytes_xlate(struct xt_xlate * xl,const struct xt_xlate_mt_params * params)156 static int connbytes_xlate(struct xt_xlate *xl,
157 			   const struct xt_xlate_mt_params *params)
158 {
159 	const struct xt_connbytes_info *info = (void *)params->match->data;
160 	unsigned long long from, to;
161 	bool invert = false;
162 
163 	xt_xlate_add(xl, "ct ");
164 
165 	switch (info->direction) {
166 	case XT_CONNBYTES_DIR_ORIGINAL:
167 		xt_xlate_add(xl, "original ");
168 		break;
169 	case XT_CONNBYTES_DIR_REPLY:
170 		xt_xlate_add(xl, "reply ");
171 		break;
172 	case XT_CONNBYTES_DIR_BOTH:
173 		break;
174 	default:
175 		return 0;
176 	}
177 
178 	switch (info->what) {
179 	case XT_CONNBYTES_PKTS:
180 		xt_xlate_add(xl, "packets ");
181 		break;
182 	case XT_CONNBYTES_BYTES:
183 		xt_xlate_add(xl, "bytes ");
184 		break;
185 	case XT_CONNBYTES_AVGPKT:
186 		xt_xlate_add(xl, "avgpkt ");
187 		break;
188 	default:
189 		return 0;
190 	}
191 
192 	if (info->count.from > info->count.to) {
193 		invert = true;
194 		from = info->count.to;
195 		to = info->count.from;
196 	} else {
197 		to = info->count.to;
198 		from = info->count.from;
199 	}
200 
201 	if (from == to)
202 		xt_xlate_add(xl, "%llu", from);
203 	else if (to == UINT64_MAX)
204 		xt_xlate_add(xl, "%s %llu", invert ? "lt" : "ge", from);
205 	else
206 		xt_xlate_add(xl, "%s%llu-%llu", invert ? "!= " : "", from, to);
207 	return 1;
208 }
209 
210 static struct xtables_match connbytes_match = {
211 	.family		= NFPROTO_UNSPEC,
212 	.name 		= "connbytes",
213 	.version 	= XTABLES_VERSION,
214 	.size 		= XT_ALIGN(sizeof(struct xt_connbytes_info)),
215 	.userspacesize	= XT_ALIGN(sizeof(struct xt_connbytes_info)),
216 	.help		= connbytes_help,
217 	.print		= connbytes_print,
218 	.save 		= connbytes_save,
219 	.x6_parse	= connbytes_parse,
220 	.x6_options	= connbytes_opts,
221 	.xlate		= connbytes_xlate,
222 };
223 
_init(void)224 void _init(void)
225 {
226 	xtables_register_match(&connbytes_match);
227 }
228