1 /* Shared library add-on to iptables to add redirect support. */
8 #include <linux/netfilter_ipv4/ip_tables.h>
9 #include <linux/netfilter/nf_nat.h>
11 #define IPT_REDIRECT_OPT_DEST 0x01
12 #define IPT_REDIRECT_OPT_RANDOM 0x02
14 /* Function which prints out usage message. */
19 "REDIRECT v%s options:\n"
20 " --to-ports <port>[-<port>]\n"
21 " Port (range) to map to.\n\n",
25 static struct option opts
[] = {
26 { "to-ports", 1, 0, '1' },
27 { "random", 0, 0, '2' },
31 /* Initialize the target. */
33 init(struct ipt_entry_target
*t
, unsigned int *nfcache
)
35 struct ip_nat_multi_range
*mr
= (struct ip_nat_multi_range
*)t
->data
;
37 /* Actually, it's 0, but it's ignored at the moment. */
44 parse_ports(const char *arg
, struct ip_nat_multi_range
*mr
)
49 mr
->range
[0].flags
|= IP_NAT_RANGE_PROTO_SPECIFIED
;
52 exit_error(PARAMETER_PROBLEM
, "IP address not permitted\n");
55 if (port
== 0 || port
> 65535)
56 exit_error(PARAMETER_PROBLEM
, "Port `%s' not valid\n", arg
);
58 dash
= strchr(arg
, '-');
60 mr
->range
[0].min
.tcp
.port
61 = mr
->range
[0].max
.tcp
.port
66 maxport
= atoi(dash
+ 1);
67 if (maxport
== 0 || maxport
> 65535)
68 exit_error(PARAMETER_PROBLEM
,
69 "Port `%s' not valid\n", dash
+1);
71 /* People are stupid. */
72 exit_error(PARAMETER_PROBLEM
,
73 "Port range `%s' funky\n", arg
);
74 mr
->range
[0].min
.tcp
.port
= htons(port
);
75 mr
->range
[0].max
.tcp
.port
= htons(maxport
);
79 /* Function which parses command options; returns true if it
82 parse(int c
, char **argv
, int invert
, unsigned int *flags
,
83 const struct ipt_entry
*entry
,
84 struct ipt_entry_target
**target
)
86 struct ip_nat_multi_range
*mr
87 = (struct ip_nat_multi_range
*)(*target
)->data
;
90 if (entry
->ip
.proto
== IPPROTO_TCP
91 || entry
->ip
.proto
== IPPROTO_UDP
92 || entry
->ip
.proto
== IPPROTO_ICMP
)
100 exit_error(PARAMETER_PROBLEM
,
101 "Need TCP or UDP with port specification");
103 if (check_inverse(optarg
, &invert
, NULL
, 0))
104 exit_error(PARAMETER_PROBLEM
,
105 "Unexpected `!' after --to-ports");
107 parse_ports(optarg
, mr
);
108 if (*flags
& IPT_REDIRECT_OPT_RANDOM
)
109 mr
->range
[0].flags
|= IP_NAT_RANGE_PROTO_RANDOM
;
110 *flags
|= IPT_REDIRECT_OPT_DEST
;
114 if (*flags
& IPT_REDIRECT_OPT_DEST
) {
115 mr
->range
[0].flags
|= IP_NAT_RANGE_PROTO_RANDOM
;
116 *flags
|= IPT_REDIRECT_OPT_RANDOM
;
118 *flags
|= IPT_REDIRECT_OPT_RANDOM
;
126 /* Final check; don't care. */
127 static void final_check(unsigned int flags
)
131 /* Prints out the targinfo. */
133 print(const struct ipt_ip
*ip
,
134 const struct ipt_entry_target
*target
,
137 struct ip_nat_multi_range
*mr
138 = (struct ip_nat_multi_range
*)target
->data
;
139 struct ip_nat_range
*r
= &mr
->range
[0];
141 if (r
->flags
& IP_NAT_RANGE_PROTO_SPECIFIED
) {
142 printf("redir ports ");
143 printf("%hu", ntohs(r
->min
.tcp
.port
));
144 if (r
->max
.tcp
.port
!= r
->min
.tcp
.port
)
145 printf("-%hu", ntohs(r
->max
.tcp
.port
));
147 if (mr
->range
[0].flags
& IP_NAT_RANGE_PROTO_RANDOM
)
152 /* Saves the union ipt_targinfo in parsable form to stdout. */
154 save(const struct ipt_ip
*ip
, const struct ipt_entry_target
*target
)
156 struct ip_nat_multi_range
*mr
157 = (struct ip_nat_multi_range
*)target
->data
;
158 struct ip_nat_range
*r
= &mr
->range
[0];
160 if (r
->flags
& IP_NAT_RANGE_PROTO_SPECIFIED
) {
161 printf("--to-ports ");
162 printf("%hu", ntohs(r
->min
.tcp
.port
));
163 if (r
->max
.tcp
.port
!= r
->min
.tcp
.port
)
164 printf("-%hu", ntohs(r
->max
.tcp
.port
));
166 if (mr
->range
[0].flags
& IP_NAT_RANGE_PROTO_RANDOM
)
171 static struct iptables_target redir
= {
174 .version
= IPTABLES_VERSION
,
175 .size
= IPT_ALIGN(sizeof(struct ip_nat_multi_range
)),
176 .userspacesize
= IPT_ALIGN(sizeof(struct ip_nat_multi_range
)),
180 .final_check
= &final_check
,
188 register_target(&redir
);