1 /* Port-triggering target.
3 * Copyright (C) 2003, CyberTAN Corporation
7 /* Shared library add-on to iptables to add port-trigger support. */
15 #include <linux/netfilter_ipv4/ip_tables.h>
16 #include <linux/netfilter_ipv4/ip_nat_rule.h>
17 #include <linux/netfilter_ipv4/ipt_TRIGGER.h>
19 /* Function which prints out usage message. */
24 "TRIGGER v%s options:\n"
25 " --trigger-type (dnat|in|out)\n"
27 " --trigger-proto proto\n"
29 " --trigger-match port[-port]\n"
30 " Trigger destination port range\n"
31 " --trigger-relate port[-port]\n"
32 " Port range to map related destination port range to.\n\n",
36 static struct option opts
[] = {
37 { "trigger-type", 1, 0, '1' },
38 { "trigger-proto", 1, 0, '2' },
39 { "trigger-match", 1, 0, '3' },
40 { "trigger-relate", 1, 0, '4' },
44 /* Initialize the target. */
46 init(struct ipt_entry_target
*t
, unsigned int *nfcache
)
48 /* Can't cache this */
49 *nfcache
|= NFC_UNKNOWN
;
54 parse_ports(const char *arg
, u_int16_t
*ports
)
60 if (port
== 0 || port
> 65535)
61 exit_error(PARAMETER_PROBLEM
, "Port range `%s' invalid\n", arg
);
63 dash
= strchr(arg
, '-');
65 ports
[0] = ports
[1] = port
;
69 maxport
= atoi(dash
+ 1);
70 if (maxport
== 0 || maxport
> 65535)
71 exit_error(PARAMETER_PROBLEM
,
72 "Port range `%s' invalid\n", dash
+1);
74 exit_error(PARAMETER_PROBLEM
,
75 "Port range `%s' invalid\n", arg
);
82 /* Function which parses command options; returns true if it
85 parse(int c
, char **argv
, int invert
, unsigned int *flags
,
86 const struct ipt_entry
*entry
,
87 struct ipt_entry_target
**target
)
89 struct ipt_trigger_info
*info
= (struct ipt_trigger_info
*)(*target
)->data
;
93 if (!strcasecmp(optarg
, "dnat"))
94 info
->type
= IPT_TRIGGER_DNAT
;
95 else if (!strcasecmp(optarg
, "in"))
96 info
->type
= IPT_TRIGGER_IN
;
97 else if (!strcasecmp(optarg
, "out"))
98 info
->type
= IPT_TRIGGER_OUT
;
100 exit_error(PARAMETER_PROBLEM
,
101 "unknown type `%s' specified", optarg
);
105 if (!strcasecmp(optarg
, "tcp"))
106 info
->proto
= IPPROTO_TCP
;
107 else if (!strcasecmp(optarg
, "udp"))
108 info
->proto
= IPPROTO_UDP
;
109 else if (!strcasecmp(optarg
, "all"))
112 exit_error(PARAMETER_PROBLEM
,
113 "unknown protocol `%s' specified", optarg
);
117 if (check_inverse(optarg
, &invert
, &optind
, 0))
118 exit_error(PARAMETER_PROBLEM
,
119 "Unexpected `!' after --trigger-match");
121 parse_ports(optarg
, info
->ports
.mport
);
125 if (check_inverse(optarg
, &invert
, &optind
, 0))
126 exit_error(PARAMETER_PROBLEM
,
127 "Unexpected `!' after --trigger-relate");
129 parse_ports(optarg
, info
->ports
.rport
);
130 *flags
|= IP_NAT_RANGE_PROTO_SPECIFIED
;
138 /* Final check; don't care. */
139 static void final_check(unsigned int flags
)
143 /* Prints out the targinfo. */
145 print(const struct ipt_ip
*ip
,
146 const struct ipt_entry_target
*target
,
149 struct ipt_trigger_info
*info
= (struct ipt_trigger_info
*)target
->data
;
152 if (info
->type
== IPT_TRIGGER_DNAT
)
153 printf("type:dnat ");
154 else if (info
->type
== IPT_TRIGGER_IN
)
156 else if (info
->type
== IPT_TRIGGER_OUT
)
159 if (info
->proto
== IPPROTO_TCP
)
161 else if (info
->proto
== IPPROTO_UDP
)
164 printf("match:%hu", info
->ports
.mport
[0]);
165 if (info
->ports
.mport
[1] > info
->ports
.mport
[0])
166 printf("-%hu", info
->ports
.mport
[1]);
169 printf("relate:%hu", info
->ports
.rport
[0]);
170 if (info
->ports
.rport
[1] > info
->ports
.rport
[0])
171 printf("-%hu", info
->ports
.rport
[1]);
175 /* Saves the union ipt_targinfo in parsable form to stdout. */
177 save(const struct ipt_ip
*ip
, const struct ipt_entry_target
*target
)
179 struct ipt_trigger_info
*info
= (struct ipt_trigger_info
*)target
->data
;
181 printf("--trigger-proto ");
182 if (info
->proto
== IPPROTO_TCP
)
184 else if (info
->proto
== IPPROTO_UDP
)
186 printf("--trigger-match %hu-%hu ", info
->ports
.mport
[0], info
->ports
.mport
[1]);
187 printf("--trigger-relate %hu-%hu ", info
->ports
.rport
[0], info
->ports
.rport
[1]);
190 static struct iptables_target trigger
= {
193 .version
= IPTABLES_VERSION
,
194 .size
= IPT_ALIGN(sizeof(struct ipt_trigger_info
)),
195 .userspacesize
= IPT_ALIGN(sizeof(struct ipt_trigger_info
)),
199 .final_check
= &final_check
,
207 register_target(&trigger
);