1 /* Shared library add-on to iptables to add redirect support. */
8 #include <limits.h> /* INT_MAX in ip_tables.h */
9 #include <linux/netfilter_ipv4/ip_tables.h>
10 #include <net/netfilter/nf_nat.h>
12 #define IPT_REDIRECT_OPT_DEST 0x01
13 #define IPT_REDIRECT_OPT_RANDOM 0x02
15 static void REDIRECT_help(void)
18 "REDIRECT target options:\n"
19 " --to-ports <port>[-<port>]\n"
20 " Port (range) to map to.\n");
23 static const struct option REDIRECT_opts
[] = {
24 { "to-ports", 1, NULL
, '1' },
25 { "random", 0, NULL
, '2' },
29 static void REDIRECT_init(struct xt_entry_target
*t
)
31 struct nf_nat_multi_range
*mr
= (struct nf_nat_multi_range
*)t
->data
;
33 /* Actually, it's 0, but it's ignored at the moment. */
40 parse_ports(const char *arg
, struct nf_nat_multi_range
*mr
)
45 mr
->range
[0].flags
|= IP_NAT_RANGE_PROTO_SPECIFIED
;
48 xtables_error(PARAMETER_PROBLEM
, "IP address not permitted\n");
52 port
= xtables_service_to_port(arg
, NULL
);
54 if (port
== 0 || port
> 65535)
55 xtables_error(PARAMETER_PROBLEM
, "Port \"%s\" not valid\n", arg
);
57 dash
= strchr(arg
, '-');
59 mr
->range
[0].min
.tcp
.port
60 = mr
->range
[0].max
.tcp
.port
65 maxport
= atoi(dash
+ 1);
66 if (maxport
== 0 || maxport
> 65535)
67 xtables_error(PARAMETER_PROBLEM
,
68 "Port `%s' not valid\n", dash
+1);
70 /* People are stupid. */
71 xtables_error(PARAMETER_PROBLEM
,
72 "Port range `%s' funky\n", arg
);
73 mr
->range
[0].min
.tcp
.port
= htons(port
);
74 mr
->range
[0].max
.tcp
.port
= htons(maxport
);
78 static int REDIRECT_parse(int c
, char **argv
, int invert
, unsigned int *flags
,
79 const void *e
, struct xt_entry_target
**target
)
81 const struct ipt_entry
*entry
= e
;
82 struct nf_nat_multi_range
*mr
83 = (struct nf_nat_multi_range
*)(*target
)->data
;
86 if (entry
->ip
.proto
== IPPROTO_TCP
87 || entry
->ip
.proto
== IPPROTO_UDP
88 || entry
->ip
.proto
== IPPROTO_SCTP
89 || entry
->ip
.proto
== IPPROTO_DCCP
90 || entry
->ip
.proto
== IPPROTO_ICMP
)
98 xtables_error(PARAMETER_PROBLEM
,
99 "Need TCP, UDP, SCTP or DCCP with port specification");
101 if (xtables_check_inverse(optarg
, &invert
, NULL
, 0))
102 xtables_error(PARAMETER_PROBLEM
,
103 "Unexpected `!' after --to-ports");
105 parse_ports(optarg
, mr
);
106 if (*flags
& IPT_REDIRECT_OPT_RANDOM
)
107 mr
->range
[0].flags
|= IP_NAT_RANGE_PROTO_RANDOM
;
108 *flags
|= IPT_REDIRECT_OPT_DEST
;
112 if (*flags
& IPT_REDIRECT_OPT_DEST
) {
113 mr
->range
[0].flags
|= IP_NAT_RANGE_PROTO_RANDOM
;
114 *flags
|= IPT_REDIRECT_OPT_RANDOM
;
116 *flags
|= IPT_REDIRECT_OPT_RANDOM
;
124 static void REDIRECT_print(const void *ip
, const struct xt_entry_target
*target
,
127 const struct nf_nat_multi_range
*mr
= (const void *)target
->data
;
128 const struct nf_nat_range
*r
= &mr
->range
[0];
130 if (r
->flags
& IP_NAT_RANGE_PROTO_SPECIFIED
) {
131 printf("redir ports ");
132 printf("%hu", ntohs(r
->min
.tcp
.port
));
133 if (r
->max
.tcp
.port
!= r
->min
.tcp
.port
)
134 printf("-%hu", ntohs(r
->max
.tcp
.port
));
136 if (mr
->range
[0].flags
& IP_NAT_RANGE_PROTO_RANDOM
)
141 static void REDIRECT_save(const void *ip
, const struct xt_entry_target
*target
)
143 const struct nf_nat_multi_range
*mr
= (const void *)target
->data
;
144 const struct nf_nat_range
*r
= &mr
->range
[0];
146 if (r
->flags
& IP_NAT_RANGE_PROTO_SPECIFIED
) {
147 printf("--to-ports ");
148 printf("%hu", ntohs(r
->min
.tcp
.port
));
149 if (r
->max
.tcp
.port
!= r
->min
.tcp
.port
)
150 printf("-%hu", ntohs(r
->max
.tcp
.port
));
152 if (mr
->range
[0].flags
& IP_NAT_RANGE_PROTO_RANDOM
)
157 static struct xtables_target redirect_tg_reg
= {
159 .version
= XTABLES_VERSION
,
160 .family
= NFPROTO_IPV4
,
161 .size
= XT_ALIGN(sizeof(struct nf_nat_multi_range
)),
162 .userspacesize
= XT_ALIGN(sizeof(struct nf_nat_multi_range
)),
163 .help
= REDIRECT_help
,
164 .init
= REDIRECT_init
,
165 .parse
= REDIRECT_parse
,
166 .print
= REDIRECT_print
,
167 .save
= REDIRECT_save
,
168 .extra_opts
= REDIRECT_opts
,
173 xtables_register_target(&redirect_tg_reg
);