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. */
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 /* Initialize the target. */
30 static void REDIRECT_init(struct xt_entry_target *t)
32 struct ip_nat_multi_range *mr = (struct ip_nat_multi_range *)t->data;
34 /* Actually, it's 0, but it's ignored at the moment. */
41 parse_ports(const char *arg, struct ip_nat_multi_range *mr)
46 mr->range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
49 exit_error(PARAMETER_PROBLEM, "IP address not permitted\n");
53 port = service_to_port(arg, NULL);
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
81 static int REDIRECT_parse(int c, char **argv, int invert, unsigned int *flags,
82 const void *e, struct xt_entry_target **target)
84 const struct ipt_entry *entry = e;
85 struct ip_nat_multi_range *mr
86 = (struct ip_nat_multi_range *)(*target)->data;
89 if (entry->ip.proto == IPPROTO_TCP
90 || entry->ip.proto == IPPROTO_UDP
91 || entry->ip.proto == IPPROTO_ICMP)
99 exit_error(PARAMETER_PROBLEM,
100 "Need TCP or UDP with port specification");
102 if (check_inverse(optarg, &invert, NULL, 0))
103 exit_error(PARAMETER_PROBLEM,
104 "Unexpected `!' after --to-ports");
106 parse_ports(optarg, mr);
107 if (*flags & IPT_REDIRECT_OPT_RANDOM)
108 mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
109 *flags |= IPT_REDIRECT_OPT_DEST;
113 if (*flags & IPT_REDIRECT_OPT_DEST) {
114 mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
115 *flags |= IPT_REDIRECT_OPT_RANDOM;
117 *flags |= IPT_REDIRECT_OPT_RANDOM;
125 /* Prints out the targinfo. */
126 static void REDIRECT_print(const void *ip, const struct xt_entry_target *target,
129 struct ip_nat_multi_range *mr
130 = (struct ip_nat_multi_range *)target->data;
131 struct ip_nat_range *r = &mr->range[0];
133 if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) {
134 printf("redir ports ");
135 printf("%hu", ntohs(r->min.tcp.port));
136 if (r->max.tcp.port != r->min.tcp.port)
137 printf("-%hu", ntohs(r->max.tcp.port));
139 if (mr->range[0].flags & IP_NAT_RANGE_PROTO_RANDOM)
144 /* Saves the union ipt_targinfo in parsable form to stdout. */
145 static void REDIRECT_save(const void *ip, const struct xt_entry_target *target)
147 struct ip_nat_multi_range *mr
148 = (struct ip_nat_multi_range *)target->data;
149 struct ip_nat_range *r = &mr->range[0];
151 if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) {
152 printf("--to-ports ");
153 printf("%hu", ntohs(r->min.tcp.port));
154 if (r->max.tcp.port != r->min.tcp.port)
155 printf("-%hu", ntohs(r->max.tcp.port));
157 if (mr->range[0].flags & IP_NAT_RANGE_PROTO_RANDOM)
162 static struct xtables_target redirect_tg_reg = {
164 .version = XTABLES_VERSION,
166 .size = XT_ALIGN(sizeof(struct ip_nat_multi_range)),
167 .userspacesize = XT_ALIGN(sizeof(struct ip_nat_multi_range)),
168 .help = REDIRECT_help,
169 .init = REDIRECT_init,
170 .parse = REDIRECT_parse,
171 .print = REDIRECT_print,
172 .save = REDIRECT_save,
173 .extra_opts = REDIRECT_opts,
178 xtables_register_target(&redirect_tg_reg);