Skip to content

Commit d1df6ab

Browse files
authored
Merge pull request #128 from pratheepa1995/BPI_port_triggering
Bpi port triggering
2 parents c21fff6 + 97b382f commit d1df6ab

File tree

6 files changed

+1200
-0
lines changed

6 files changed

+1200
-0
lines changed
Lines changed: 389 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,389 @@
1+
Source: Backport from http://asuswrt-merlin.ng/
2+
Index: iptables-1.8.4/extensions/libipt_TRIGGER.c
3+
===================================================================
4+
--- /dev/null
5+
+++ iptables-1.8.4/extensions/libipt_TRIGGER.c
6+
@@ -0,0 +1,347 @@
7+
+/* Port-triggering target.
8+
+ *
9+
+ * Copyright (C) 2003, CyberTAN Corporation
10+
+ * All Rights Reserved.
11+
+ */
12+
+
13+
+/* Shared library add-on to iptables to add port-trigger support. */
14+
+
15+
+#include <stdio.h>
16+
+#include <string.h>
17+
+#include <stdlib.h>
18+
+#include <getopt.h>
19+
+#include <xtables.h>
20+
+#include <linux/netfilter_ipv4/ip_tables.h>
21+
+#include <linux/netfilter_ipv4/ipt_TRIGGER.h>
22+
+
23+
+
24+
+#define IPT_TRIGGER_USED (1) << 0
25+
+#define IPT_TRIGGER_MATCH_USED (1) << 1
26+
+#define IPT_TRIGGER_RELATE_USED (1) << 2
27+
+#define IPT_TRIGGER_DNAT_USED (1) << 3
28+
+#define IPT_TRIGGER_IN_USED (1) << 4
29+
+#define IPT_TRIGGER_OUT_USED (1) << 5
30+
+#define IPT_TRIGGER_PROTO_USED (1) << 6
31+
+
32+
+static void
33+
+parse_tcp_ports(const char *portstring, u_int16_t *ports)
34+
+{
35+
+ char *buffer;
36+
+ char *cp;
37+
+
38+
+ buffer = strdup(portstring);
39+
+ if ((cp = strchr(buffer, ':')) == NULL)
40+
+ ports[0] = ports[1] = xtables_parse_port(buffer, "tcp");
41+
+ else {
42+
+ *cp = '\0';
43+
+ cp++;
44+
+
45+
+ ports[0] = buffer[0] ? xtables_parse_port(buffer, "tcp") : 0;
46+
+ ports[1] = cp[0] ? xtables_parse_port(cp, "tcp") : 0xFFFF;
47+
+
48+
+ if (ports[0] > ports[1])
49+
+ xtables_error(PARAMETER_PROBLEM,
50+
+ "invalid portrange (min > max)");
51+
+ }
52+
+ free(buffer);
53+
+}
54+
+
55+
+/* Function which prints out usage message. */
56+
+
57+
+static void TRIGGER_help(void)
58+
+{
59+
+ printf(
60+
+ "TRIGGER options:\n"
61+
+ " --trigger-type (dnat|in|out)\n"
62+
+ "'\t\t Trigger type\n"
63+
+ " --trigger-proto proto\n"
64+
+ "\t\t Trigger protocol tcp|udp|all\n"
65+
+ " --trigger-match port[-port]\n"
66+
+ "\t\tTrigger destination port range\n"
67+
+ " --trigger-relate port[-port]\n"
68+
+ "\t\tPort range to map related destination port range to.\n\n"
69+
+ );
70+
+}
71+
+/* man 3 getopt structure */
72+
+static struct option TRIGGER_opts[] = {
73+
+ { "trigger-type", 1, NULL, '1' },
74+
+ { "trigger-proto", 1, NULL, '2' },
75+
+ { "trigger-match", 1, NULL, '3' },
76+
+ { "trigger-relate", 1, NULL, '4' },
77+
+ { .name = NULL }
78+
+
79+
+};
80+
+
81+
+
82+
+
83+
+/* Parses ports */
84+
+static int parse_ports(const char *arg, u_int16_t *ports)
85+
+{
86+
+ const char *dash;
87+
+ int port;
88+
+ ports[0] = 0;
89+
+ ports[1] = 0;
90+
+
91+
+ dash = strchr(arg, ':');
92+
+ if (dash == NULL) {
93+
+ port = ( u_int16_t ) atoi(arg );
94+
+ if (port == 0 || port > 65535) {
95+
+ xtables_error(PARAMETER_PROBLEM, "Invalid Port %d \n", port);
96+
+ return -1; /* not OK */
97+
+ }
98+
+ ports[0] = port;
99+
+ ports[1] = 0;
100+
+ }
101+
+ else {
102+
+ int portEnd;
103+
+
104+
+ port=strtol(arg, NULL, 10);
105+
+ portEnd = ( u_int16_t ) atoi(dash + 1);
106+
+ if (portEnd == 0 || portEnd > 65535 || ( portEnd < port ))
107+
+ {
108+
+ xtables_error(PARAMETER_PROBLEM, "Port range %d:%d is invalid\n", port, portEnd);
109+
+ return -1; /* not OK */
110+
+ }
111+
+ ports[0] = port;
112+
+ ports[1] = portEnd;
113+
+ }
114+
+ return 1;
115+
+}
116+
+
117+
+
118+
+/* Function which parses command options; returns true if it
119+
+ ate an option */
120+
+
121+
+static int
122+
+TRIGGER_parse(int c, char **argv, int invert, unsigned int *flags,
123+
+ const void *entry,
124+
+ struct xt_entry_target **target)
125+
+{
126+
+ struct ipt_trigger_info *info = (struct ipt_trigger_info *) (*target)->data;
127+
+
128+
+ if ( info == NULL )
129+
+ {
130+
+ xtables_error(PARAMETER_PROBLEM, "NULL paramaeter (*target)->data specified" );
131+
+ return 0;
132+
+ }
133+
+ if ( optarg == NULL )
134+
+ {
135+
+ xtables_error(PARAMETER_PROBLEM, "NULL paramaeter optarg specified" );
136+
+ return 0;
137+
+ }
138+
+
139+
+ /* Parse argument number 1, 2,3, 4 */
140+
+ switch (c) {
141+
+ case '1':
142+
+ {
143+
+ if (!strncasecmp(optarg, "dnat",3))
144+
+ {
145+
+ info->type = IPT_TRIGGER_DNAT;
146+
+ *flags |= IPT_TRIGGER_DNAT_USED;
147+
+ }
148+
+ else if (!strncasecmp(optarg, "in",2))
149+
+ {
150+
+ info->type = IPT_TRIGGER_IN;
151+
+ *flags |= IPT_TRIGGER_IN_USED;
152+
+ }
153+
+ else if (!strncasecmp(optarg, "out",3))
154+
+ {
155+
+ info->type = IPT_TRIGGER_OUT;
156+
+ *flags |= IPT_TRIGGER_OUT_USED;
157+
+ }
158+
+ else
159+
+ {
160+
+ xtables_error(PARAMETER_PROBLEM, "unknown type trigger type specified");
161+
+ return 0;
162+
+ }
163+
+ return 1;
164+
+ }
165+
+
166+
+ case '2':
167+
+ {
168+
+ if (!strncasecmp(optarg, "tcp",3))
169+
+ {
170+
+ info->proto = IPPROTO_TCP;
171+
+ *flags |= IPT_TRIGGER_PROTO_USED;
172+
+ }
173+
+ else if (!strncasecmp(optarg, "udp",3))
174+
+ {
175+
+ info->proto = IPPROTO_UDP;
176+
+ *flags |= IPT_TRIGGER_PROTO_USED;
177+
+ }
178+
+ else if (!strncasecmp(optarg, "all",3))
179+
+ {
180+
+ info->proto = IPT_TRIGGER_BOTH_PROTOCOLS;
181+
+ *flags |= IPT_TRIGGER_PROTO_USED;
182+
+ }
183+
+ else if (!strncasecmp(optarg, "both",4))
184+
+ {
185+
+ info->proto = IPT_TRIGGER_BOTH_PROTOCOLS;
186+
+ *flags |= IPT_TRIGGER_PROTO_USED;
187+
+ }
188+
+ else
189+
+ {
190+
+ xtables_error(PARAMETER_PROBLEM, "unknown protocol specified");
191+
+ }
192+
+ return 1;
193+
+ }
194+
+
195+
+ case '3':
196+
+ {
197+
+ if (invert) /* Operator NOT is not supported */
198+
+ {
199+
+ xtables_error(PARAMETER_PROBLEM, "Unexpected `!' after --trigger-match");
200+
+ return 0;
201+
+
202+
+ }
203+
+ if (parse_ports(optarg, info->ports.mport))
204+
+ {
205+
+ *flags |= IPT_TRIGGER_MATCH_USED;
206+
+ *flags |= IPT_TRIGGER_USED;
207+
+ return 1;
208+
+ }
209+
+ }
210+
+
211+
+ case '4':
212+
+ {
213+
+ if (invert) /* Operator NOT is not supported */
214+
+ {
215+
+ xtables_error(PARAMETER_PROBLEM, "Unexpected `!' after --trigger-relate");
216+
+
217+
+ }
218+
+ if (parse_ports(optarg, info->ports.rport))
219+
+ {
220+
+ *flags |= IPT_TRIGGER_RELATE_USED;
221+
+ *flags |= IPT_TRIGGER_USED;
222+
+ return 1;
223+
+ }
224+
+ }
225+
+
226+
+ default:
227+
+ return 0; /* NOK */
228+
+ }
229+
+ return 0; /* NOK */
230+
+}
231+
+
232+
+
233+
+/* Prints out the targinfo. iptables -L */
234+
+static void TRIGGER_print(const void *ip,
235+
+ const struct xt_entry_target *target, int numeric)
236+
+{
237+
+ struct ipt_trigger_info *info = (struct ipt_trigger_info *)target->data;
238+
+
239+
+ printf(" TRIGGER ");
240+
+ if (info->type == IPT_TRIGGER_DNAT)
241+
+ printf("type:dnat ");
242+
+ else if (info->type == IPT_TRIGGER_IN)
243+
+ printf("type:in ");
244+
+ else if (info->type == IPT_TRIGGER_OUT)
245+
+ printf("type:out ");
246+
+ if (info->type == IPT_TRIGGER_OUT) /* only trigger-type out specifies other parameters */
247+
+ {
248+
+ if (info->proto == IPPROTO_TCP)
249+
+ printf("tcp ");
250+
+ else if (info->proto == IPPROTO_UDP)
251+
+ printf("udp ");
252+
+ else if (info->proto == IPT_TRIGGER_BOTH_PROTOCOLS)
253+
+ printf("both ");
254+
+ else
255+
+ printf("all ");
256+
+
257+
+ printf("match:%hu", info->ports.mport[0]);
258+
+ if (info->ports.mport[1] > info->ports.mport[0])
259+
+ printf("-%hu", info->ports.mport[1]);
260+
+ printf(" ");
261+
+
262+
+ printf("relate:%hu", info->ports.rport[0]);
263+
+ if (info->ports.rport[1] > info->ports.rport[0])
264+
+ printf("-%hu", info->ports.rport[1]);
265+
+ }
266+
+ printf(" ");
267+
+}
268+
+/*
269+
+*
270+
+* last chance for sanity check.
271+
+* It's called when the user enter a new rule, right after arguments parsing is done.
272+
+*
273+
+*/
274+
+
275+
+static void TRIGGER_final_check(unsigned int flags)
276+
+{
277+
+ if (flags & IPT_TRIGGER_OUT_USED)
278+
+ {
279+
+ if (!(flags & IPT_TRIGGER_RELATE_USED))
280+
+ {
281+
+ xtables_error(PARAMETER_PROBLEM, "TRIGGER: You must specify trigger relate an parameter");
282+
+ }
283+
+ if (!(flags & IPT_TRIGGER_MATCH_USED))
284+
+ {
285+
+ xtables_error(PARAMETER_PROBLEM, "TRIGGER: You must specify trigger match an parameter");
286+
+ }
287+
+ if (!(flags & IPT_TRIGGER_OUT_USED))
288+
+ {
289+
+ xtables_error(PARAMETER_PROBLEM, "TRIGGER: You must specify trigger type an parameter");
290+
+ }
291+
+ if (!(flags & IPT_TRIGGER_PROTO_USED))
292+
+ {
293+
+ xtables_error(PARAMETER_PROBLEM, "TRIGGER: You must specify trigger protocols an parameter");
294+
+ }
295+
+
296+
+ }
297+
+}
298+
+
299+
+/*
300+
+* If we have a ruleset that we want to save, iptables provide the tool 'iptables-save' which dumps all your rules. It obviously needs your extension's help to dump proper rules.
301+
+* This is done by calling this function.
302+
+*
303+
+*
304+
+*/
305+
+
306+
+
307+
+static void TRIGGER_save(const void *ip, const struct xt_entry_target *target)
308+
+{
309+
+ struct ipt_trigger_info *info = (struct ipt_trigger_info *)target->data;
310+
+
311+
+ printf(" --trigger-proto ");
312+
+ if (info->proto == IPPROTO_TCP)
313+
+ printf("tcp ");
314+
+ else if (info->proto == IPPROTO_UDP)
315+
+ printf("udp ");
316+
+ else if (info->proto == IPT_TRIGGER_BOTH_PROTOCOLS)
317+
+ printf("both ");
318+
+ else
319+
+ printf("all ");
320+
+ printf(" --trigger-match %hu", info->ports.mport[0]);
321+
+ if (info->ports.mport[1])
322+
+ printf("-%hu", info->ports.mport[1]);
323+
+ printf(" ");
324+
+ printf(" --trigger-relate %hu", info->ports.rport[0]);
325+
+ if (info->ports.rport[1])
326+
+ printf("-%hu", info->ports.rport[1]);
327+
+ printf(" ");
328+
+}
329+
+
330+
+
331+
+static struct xtables_target trigger_tg_reg = {
332+
+ .name = "TRIGGER",
333+
+ .version = XTABLES_VERSION,
334+
+ .family = NFPROTO_IPV4,
335+
+ .size = XT_ALIGN(sizeof(struct ipt_trigger_info)),
336+
+ .userspacesize = XT_ALIGN(sizeof(struct ipt_trigger_info)),
337+
+ .help = TRIGGER_help,
338+
+ .parse = TRIGGER_parse,
339+
+ .final_check = TRIGGER_final_check,
340+
+ .print = TRIGGER_print,
341+
+ .save = TRIGGER_save,
342+
+ .extra_opts = TRIGGER_opts,
343+
+};
344+
+
345+
+void _init(void)
346+
+{
347+
+/*
348+
+*
349+
+* This function is called when the module is loaded by iptables.
350+
+* man dlopen.
351+
+*/
352+
+ xtables_register_target(&trigger_tg_reg);
353+
+}
354+
Index: iptables-1.8.4/include/linux/netfilter_ipv4/ipt_TRIGGER.h
355+
===================================================================
356+
--- /dev/null
357+
+++ iptables-1.8.4/include/linux/netfilter_ipv4/ipt_TRIGGER.h
358+
@@ -0,0 +1,31 @@
359+
+/* Port-triggering target.
360+
+ *
361+
+ * Copyright (C) 2003, CyberTAN Corporation
362+
+ * All Rights Reserved.
363+
+ */
364+
+
365+
+/* Shared library add-on to iptables to add port-trigger support. */
366+
+
367+
+#ifndef _IPT_TRIGGER_H_target
368+
+#define _IPT_TRIGGER_H_target
369+
+#define IPT_TRIGGER_BOTH_PROTOCOLS 253 /* unassigned number */
370+
+
371+
+enum ipt_trigger_type
372+
+{
373+
+ IPT_TRIGGER_DNAT = 1,
374+
+ IPT_TRIGGER_IN = 2,
375+
+ IPT_TRIGGER_OUT = 3
376+
+};
377+
+
378+
+struct ipt_trigger_ports {
379+
+ u_int16_t mport[2]; /* Related destination port range */
380+
+ u_int16_t rport[2]; /* Port range to map related destination port range to */
381+
+};
382+
+
383+
+struct ipt_trigger_info {
384+
+ enum ipt_trigger_type type;
385+
+ u_int16_t proto; /* Related protocol */
386+
+ struct ipt_trigger_ports ports;
387+
+};
388+
+
389+
+#endif /*_IPT_TRIGGER_H_target*/
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
RRECOMMENDS_${PN}_append += "kernel-module-xt-nat \
2+
kernel-module-ipt-trigger"
3+
4+
5+
FILESEXTRAPATHS_prepend:="${THISDIR}/files:"
6+
7+
SRC_URI_append = "file://0001-add-port-triggering-support.patch"

0 commit comments

Comments
 (0)