1*a71a9546SAutomerger Merge Worker /*
2*a71a9546SAutomerger Merge Worker * Copyright (c) 2011 Patrick McHardy <[email protected]>
3*a71a9546SAutomerger Merge Worker *
4*a71a9546SAutomerger Merge Worker * Based on Rusty Russell's IPv4 DNAT target. Development of IPv6 NAT
5*a71a9546SAutomerger Merge Worker * funded by Astaro.
6*a71a9546SAutomerger Merge Worker */
7*a71a9546SAutomerger Merge Worker
8*a71a9546SAutomerger Merge Worker #include <stdio.h>
9*a71a9546SAutomerger Merge Worker #include <netdb.h>
10*a71a9546SAutomerger Merge Worker #include <string.h>
11*a71a9546SAutomerger Merge Worker #include <stdlib.h>
12*a71a9546SAutomerger Merge Worker #include <xtables.h>
13*a71a9546SAutomerger Merge Worker #include <iptables.h> /* get_kernel_version */
14*a71a9546SAutomerger Merge Worker #include <limits.h> /* INT_MAX in ip_tables.h */
15*a71a9546SAutomerger Merge Worker #include <arpa/inet.h>
16*a71a9546SAutomerger Merge Worker #include <linux/netfilter_ipv4/ip_tables.h>
17*a71a9546SAutomerger Merge Worker #include <linux/netfilter_ipv6/ip6_tables.h>
18*a71a9546SAutomerger Merge Worker #include <linux/netfilter/nf_nat.h>
19*a71a9546SAutomerger Merge Worker
20*a71a9546SAutomerger Merge Worker #define TO_IPV4_MRC(ptr) ((const struct nf_nat_ipv4_multi_range_compat *)(ptr))
21*a71a9546SAutomerger Merge Worker #define RANGE2_INIT_FROM_IPV4_MRC(ptr) { \
22*a71a9546SAutomerger Merge Worker .flags = TO_IPV4_MRC(ptr)->range[0].flags, \
23*a71a9546SAutomerger Merge Worker .min_addr.ip = TO_IPV4_MRC(ptr)->range[0].min_ip, \
24*a71a9546SAutomerger Merge Worker .max_addr.ip = TO_IPV4_MRC(ptr)->range[0].max_ip, \
25*a71a9546SAutomerger Merge Worker .min_proto = TO_IPV4_MRC(ptr)->range[0].min, \
26*a71a9546SAutomerger Merge Worker .max_proto = TO_IPV4_MRC(ptr)->range[0].max, \
27*a71a9546SAutomerger Merge Worker };
28*a71a9546SAutomerger Merge Worker #define TO_NF_NAT_RANGE(ptr) ((const struct nf_nat_range *)(ptr))
29*a71a9546SAutomerger Merge Worker #define RANGE2_INIT_FROM_RANGE(ptr) { \
30*a71a9546SAutomerger Merge Worker .flags = TO_NF_NAT_RANGE(ptr)->flags, \
31*a71a9546SAutomerger Merge Worker .min_addr = TO_NF_NAT_RANGE(ptr)->min_addr, \
32*a71a9546SAutomerger Merge Worker .max_addr = TO_NF_NAT_RANGE(ptr)->max_addr, \
33*a71a9546SAutomerger Merge Worker .min_proto = TO_NF_NAT_RANGE(ptr)->min_proto, \
34*a71a9546SAutomerger Merge Worker .max_proto = TO_NF_NAT_RANGE(ptr)->max_proto, \
35*a71a9546SAutomerger Merge Worker };
36*a71a9546SAutomerger Merge Worker
37*a71a9546SAutomerger Merge Worker enum {
38*a71a9546SAutomerger Merge Worker O_TO_DEST = 0,
39*a71a9546SAutomerger Merge Worker O_TO_SRC,
40*a71a9546SAutomerger Merge Worker O_TO_PORTS,
41*a71a9546SAutomerger Merge Worker O_RANDOM,
42*a71a9546SAutomerger Merge Worker O_RANDOM_FULLY,
43*a71a9546SAutomerger Merge Worker O_PERSISTENT,
44*a71a9546SAutomerger Merge Worker };
45*a71a9546SAutomerger Merge Worker
SNAT_help(void)46*a71a9546SAutomerger Merge Worker static void SNAT_help(void)
47*a71a9546SAutomerger Merge Worker {
48*a71a9546SAutomerger Merge Worker printf(
49*a71a9546SAutomerger Merge Worker "SNAT target options:\n"
50*a71a9546SAutomerger Merge Worker " --to-source [<ipaddr>[-<ipaddr>]][:port[-port]]\n"
51*a71a9546SAutomerger Merge Worker " Address to map source to.\n"
52*a71a9546SAutomerger Merge Worker "[--random] [--random-fully] [--persistent]\n");
53*a71a9546SAutomerger Merge Worker }
54*a71a9546SAutomerger Merge Worker
MASQUERADE_help(void)55*a71a9546SAutomerger Merge Worker static void MASQUERADE_help(void)
56*a71a9546SAutomerger Merge Worker {
57*a71a9546SAutomerger Merge Worker printf(
58*a71a9546SAutomerger Merge Worker "MASQUERADE target options:\n"
59*a71a9546SAutomerger Merge Worker " --to-ports <port>[-<port>]\n"
60*a71a9546SAutomerger Merge Worker " Port (range) to map to.\n"
61*a71a9546SAutomerger Merge Worker " --random\n"
62*a71a9546SAutomerger Merge Worker " Randomize source port.\n"
63*a71a9546SAutomerger Merge Worker " --random-fully\n"
64*a71a9546SAutomerger Merge Worker " Fully randomize source port.\n");
65*a71a9546SAutomerger Merge Worker }
66*a71a9546SAutomerger Merge Worker
DNAT_help(void)67*a71a9546SAutomerger Merge Worker static void DNAT_help(void)
68*a71a9546SAutomerger Merge Worker {
69*a71a9546SAutomerger Merge Worker printf(
70*a71a9546SAutomerger Merge Worker "DNAT target options:\n"
71*a71a9546SAutomerger Merge Worker " --to-destination [<ipaddr>[-<ipaddr>]][:port[-port]]\n"
72*a71a9546SAutomerger Merge Worker " Address to map destination to.\n"
73*a71a9546SAutomerger Merge Worker "[--random] [--persistent]\n");
74*a71a9546SAutomerger Merge Worker }
75*a71a9546SAutomerger Merge Worker
DNAT_help_v2(void)76*a71a9546SAutomerger Merge Worker static void DNAT_help_v2(void)
77*a71a9546SAutomerger Merge Worker {
78*a71a9546SAutomerger Merge Worker printf(
79*a71a9546SAutomerger Merge Worker "DNAT target options:\n"
80*a71a9546SAutomerger Merge Worker " --to-destination [<ipaddr>[-<ipaddr>]][:port[-port[/port]]]\n"
81*a71a9546SAutomerger Merge Worker " Address to map destination to.\n"
82*a71a9546SAutomerger Merge Worker "[--random] [--persistent]\n");
83*a71a9546SAutomerger Merge Worker }
84*a71a9546SAutomerger Merge Worker
REDIRECT_help(void)85*a71a9546SAutomerger Merge Worker static void REDIRECT_help(void)
86*a71a9546SAutomerger Merge Worker {
87*a71a9546SAutomerger Merge Worker printf(
88*a71a9546SAutomerger Merge Worker "REDIRECT target options:\n"
89*a71a9546SAutomerger Merge Worker " --to-ports <port>[-<port>]\n"
90*a71a9546SAutomerger Merge Worker " Port (range) to map to.\n"
91*a71a9546SAutomerger Merge Worker " [--random]\n");
92*a71a9546SAutomerger Merge Worker }
93*a71a9546SAutomerger Merge Worker
94*a71a9546SAutomerger Merge Worker static const struct xt_option_entry SNAT_opts[] = {
95*a71a9546SAutomerger Merge Worker {.name = "to-source", .id = O_TO_SRC, .type = XTTYPE_STRING,
96*a71a9546SAutomerger Merge Worker .flags = XTOPT_MAND},
97*a71a9546SAutomerger Merge Worker {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
98*a71a9546SAutomerger Merge Worker {.name = "random-fully", .id = O_RANDOM_FULLY, .type = XTTYPE_NONE},
99*a71a9546SAutomerger Merge Worker {.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE},
100*a71a9546SAutomerger Merge Worker XTOPT_TABLEEND,
101*a71a9546SAutomerger Merge Worker };
102*a71a9546SAutomerger Merge Worker
103*a71a9546SAutomerger Merge Worker static const struct xt_option_entry MASQUERADE_opts[] = {
104*a71a9546SAutomerger Merge Worker {.name = "to-ports", .id = O_TO_PORTS, .type = XTTYPE_STRING},
105*a71a9546SAutomerger Merge Worker {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
106*a71a9546SAutomerger Merge Worker {.name = "random-fully", .id = O_RANDOM_FULLY, .type = XTTYPE_NONE},
107*a71a9546SAutomerger Merge Worker XTOPT_TABLEEND,
108*a71a9546SAutomerger Merge Worker };
109*a71a9546SAutomerger Merge Worker
110*a71a9546SAutomerger Merge Worker static const struct xt_option_entry DNAT_opts[] = {
111*a71a9546SAutomerger Merge Worker {.name = "to-destination", .id = O_TO_DEST, .type = XTTYPE_STRING,
112*a71a9546SAutomerger Merge Worker .flags = XTOPT_MAND},
113*a71a9546SAutomerger Merge Worker {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
114*a71a9546SAutomerger Merge Worker {.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE},
115*a71a9546SAutomerger Merge Worker XTOPT_TABLEEND,
116*a71a9546SAutomerger Merge Worker };
117*a71a9546SAutomerger Merge Worker
118*a71a9546SAutomerger Merge Worker static const struct xt_option_entry REDIRECT_opts[] = {
119*a71a9546SAutomerger Merge Worker {.name = "to-ports", .id = O_TO_PORTS, .type = XTTYPE_STRING},
120*a71a9546SAutomerger Merge Worker {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
121*a71a9546SAutomerger Merge Worker XTOPT_TABLEEND,
122*a71a9546SAutomerger Merge Worker };
123*a71a9546SAutomerger Merge Worker
124*a71a9546SAutomerger Merge Worker /* Parses ports */
125*a71a9546SAutomerger Merge Worker static void
parse_ports(const char * arg,bool portok,struct nf_nat_range2 * range)126*a71a9546SAutomerger Merge Worker parse_ports(const char *arg, bool portok, struct nf_nat_range2 *range)
127*a71a9546SAutomerger Merge Worker {
128*a71a9546SAutomerger Merge Worker unsigned int port, maxport, baseport;
129*a71a9546SAutomerger Merge Worker char *end = NULL;
130*a71a9546SAutomerger Merge Worker
131*a71a9546SAutomerger Merge Worker if (!portok)
132*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
133*a71a9546SAutomerger Merge Worker "Need TCP, UDP, SCTP or DCCP with port specification");
134*a71a9546SAutomerger Merge Worker
135*a71a9546SAutomerger Merge Worker range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
136*a71a9546SAutomerger Merge Worker
137*a71a9546SAutomerger Merge Worker if (!xtables_strtoui(arg, &end, &port, 0, UINT16_MAX)) {
138*a71a9546SAutomerger Merge Worker port = xtables_service_to_port(arg, NULL);
139*a71a9546SAutomerger Merge Worker if (port == (unsigned)-1)
140*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
141*a71a9546SAutomerger Merge Worker "Port `%s' not valid", arg);
142*a71a9546SAutomerger Merge Worker end = "";
143*a71a9546SAutomerger Merge Worker }
144*a71a9546SAutomerger Merge Worker
145*a71a9546SAutomerger Merge Worker switch (*end) {
146*a71a9546SAutomerger Merge Worker case '\0':
147*a71a9546SAutomerger Merge Worker range->min_proto.tcp.port
148*a71a9546SAutomerger Merge Worker = range->max_proto.tcp.port
149*a71a9546SAutomerger Merge Worker = htons(port);
150*a71a9546SAutomerger Merge Worker return;
151*a71a9546SAutomerger Merge Worker case '-':
152*a71a9546SAutomerger Merge Worker arg = end + 1;
153*a71a9546SAutomerger Merge Worker break;
154*a71a9546SAutomerger Merge Worker case ':':
155*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
156*a71a9546SAutomerger Merge Worker "Invalid port:port syntax - use dash");
157*a71a9546SAutomerger Merge Worker default:
158*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
159*a71a9546SAutomerger Merge Worker "Garbage after port value: `%s'", end);
160*a71a9546SAutomerger Merge Worker }
161*a71a9546SAutomerger Merge Worker
162*a71a9546SAutomerger Merge Worker /* it is a range, don't allow service names here */
163*a71a9546SAutomerger Merge Worker if (!xtables_strtoui(arg, &end, &maxport, 0, UINT16_MAX))
164*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM, "Port `%s' not valid", arg);
165*a71a9546SAutomerger Merge Worker
166*a71a9546SAutomerger Merge Worker if (maxport < port)
167*a71a9546SAutomerger Merge Worker /* People are stupid. */
168*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
169*a71a9546SAutomerger Merge Worker "Port range `%s' funky", arg);
170*a71a9546SAutomerger Merge Worker
171*a71a9546SAutomerger Merge Worker range->min_proto.tcp.port = htons(port);
172*a71a9546SAutomerger Merge Worker range->max_proto.tcp.port = htons(maxport);
173*a71a9546SAutomerger Merge Worker
174*a71a9546SAutomerger Merge Worker switch (*end) {
175*a71a9546SAutomerger Merge Worker case '\0':
176*a71a9546SAutomerger Merge Worker return;
177*a71a9546SAutomerger Merge Worker case '/':
178*a71a9546SAutomerger Merge Worker arg = end + 1;
179*a71a9546SAutomerger Merge Worker break;
180*a71a9546SAutomerger Merge Worker default:
181*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
182*a71a9546SAutomerger Merge Worker "Garbage after port range: `%s'", end);
183*a71a9546SAutomerger Merge Worker }
184*a71a9546SAutomerger Merge Worker
185*a71a9546SAutomerger Merge Worker if (!xtables_strtoui(arg, &end, &baseport, 1, UINT16_MAX)) {
186*a71a9546SAutomerger Merge Worker baseport = xtables_service_to_port(arg, NULL);
187*a71a9546SAutomerger Merge Worker if (baseport == (unsigned)-1)
188*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
189*a71a9546SAutomerger Merge Worker "Port `%s' not valid", arg);
190*a71a9546SAutomerger Merge Worker }
191*a71a9546SAutomerger Merge Worker
192*a71a9546SAutomerger Merge Worker range->flags |= NF_NAT_RANGE_PROTO_OFFSET;
193*a71a9546SAutomerger Merge Worker range->base_proto.tcp.port = htons(baseport);
194*a71a9546SAutomerger Merge Worker }
195*a71a9546SAutomerger Merge Worker
196*a71a9546SAutomerger Merge Worker /* Ranges expected in network order. */
197*a71a9546SAutomerger Merge Worker static void
parse_to(const char * orig_arg,bool portok,struct nf_nat_range2 * range,int family)198*a71a9546SAutomerger Merge Worker parse_to(const char *orig_arg, bool portok,
199*a71a9546SAutomerger Merge Worker struct nf_nat_range2 *range, int family)
200*a71a9546SAutomerger Merge Worker {
201*a71a9546SAutomerger Merge Worker char *arg, *start, *end, *colon, *dash;
202*a71a9546SAutomerger Merge Worker
203*a71a9546SAutomerger Merge Worker arg = xtables_strdup(orig_arg);
204*a71a9546SAutomerger Merge Worker start = strchr(arg, '[');
205*a71a9546SAutomerger Merge Worker if (!start) {
206*a71a9546SAutomerger Merge Worker start = arg;
207*a71a9546SAutomerger Merge Worker /* Lets assume one colon is port information.
208*a71a9546SAutomerger Merge Worker * Otherwise its an IPv6 address */
209*a71a9546SAutomerger Merge Worker colon = strchr(arg, ':');
210*a71a9546SAutomerger Merge Worker if (colon && strchr(colon + 1, ':'))
211*a71a9546SAutomerger Merge Worker colon = NULL;
212*a71a9546SAutomerger Merge Worker } else {
213*a71a9546SAutomerger Merge Worker start++;
214*a71a9546SAutomerger Merge Worker end = strchr(start, ']');
215*a71a9546SAutomerger Merge Worker if (end == NULL || family == AF_INET)
216*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
217*a71a9546SAutomerger Merge Worker "Invalid address format");
218*a71a9546SAutomerger Merge Worker
219*a71a9546SAutomerger Merge Worker *end = '\0';
220*a71a9546SAutomerger Merge Worker colon = strchr(end + 1, ':');
221*a71a9546SAutomerger Merge Worker }
222*a71a9546SAutomerger Merge Worker
223*a71a9546SAutomerger Merge Worker if (colon) {
224*a71a9546SAutomerger Merge Worker parse_ports(colon + 1, portok, range);
225*a71a9546SAutomerger Merge Worker
226*a71a9546SAutomerger Merge Worker /* Starts with colon or [] colon? No IP info...*/
227*a71a9546SAutomerger Merge Worker if (colon == arg || colon == arg + 2) {
228*a71a9546SAutomerger Merge Worker free(arg);
229*a71a9546SAutomerger Merge Worker return;
230*a71a9546SAutomerger Merge Worker }
231*a71a9546SAutomerger Merge Worker *colon = '\0';
232*a71a9546SAutomerger Merge Worker }
233*a71a9546SAutomerger Merge Worker
234*a71a9546SAutomerger Merge Worker range->flags |= NF_NAT_RANGE_MAP_IPS;
235*a71a9546SAutomerger Merge Worker dash = strchr(start, '-');
236*a71a9546SAutomerger Merge Worker if (colon && dash && dash > colon)
237*a71a9546SAutomerger Merge Worker dash = NULL;
238*a71a9546SAutomerger Merge Worker
239*a71a9546SAutomerger Merge Worker if (dash)
240*a71a9546SAutomerger Merge Worker *dash = '\0';
241*a71a9546SAutomerger Merge Worker
242*a71a9546SAutomerger Merge Worker if (!inet_pton(family, start, &range->min_addr))
243*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
244*a71a9546SAutomerger Merge Worker "Bad IP address \"%s\"", start);
245*a71a9546SAutomerger Merge Worker if (dash) {
246*a71a9546SAutomerger Merge Worker if (!inet_pton(family, dash + 1, &range->max_addr))
247*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
248*a71a9546SAutomerger Merge Worker "Bad IP address \"%s\"", dash + 1);
249*a71a9546SAutomerger Merge Worker } else {
250*a71a9546SAutomerger Merge Worker range->max_addr = range->min_addr;
251*a71a9546SAutomerger Merge Worker }
252*a71a9546SAutomerger Merge Worker free(arg);
253*a71a9546SAutomerger Merge Worker return;
254*a71a9546SAutomerger Merge Worker }
255*a71a9546SAutomerger Merge Worker
__NAT_parse(struct xt_option_call * cb,__u16 proto,struct nf_nat_range2 * range,int family)256*a71a9546SAutomerger Merge Worker static void __NAT_parse(struct xt_option_call *cb, __u16 proto,
257*a71a9546SAutomerger Merge Worker struct nf_nat_range2 *range, int family)
258*a71a9546SAutomerger Merge Worker {
259*a71a9546SAutomerger Merge Worker bool portok = proto == IPPROTO_TCP ||
260*a71a9546SAutomerger Merge Worker proto == IPPROTO_UDP ||
261*a71a9546SAutomerger Merge Worker proto == IPPROTO_SCTP ||
262*a71a9546SAutomerger Merge Worker proto == IPPROTO_DCCP ||
263*a71a9546SAutomerger Merge Worker proto == IPPROTO_ICMP;
264*a71a9546SAutomerger Merge Worker
265*a71a9546SAutomerger Merge Worker xtables_option_parse(cb);
266*a71a9546SAutomerger Merge Worker switch (cb->entry->id) {
267*a71a9546SAutomerger Merge Worker case O_TO_DEST:
268*a71a9546SAutomerger Merge Worker case O_TO_SRC:
269*a71a9546SAutomerger Merge Worker parse_to(cb->arg, portok, range, family);
270*a71a9546SAutomerger Merge Worker break;
271*a71a9546SAutomerger Merge Worker case O_TO_PORTS:
272*a71a9546SAutomerger Merge Worker parse_ports(cb->arg, portok, range);
273*a71a9546SAutomerger Merge Worker break;
274*a71a9546SAutomerger Merge Worker case O_PERSISTENT:
275*a71a9546SAutomerger Merge Worker range->flags |= NF_NAT_RANGE_PERSISTENT;
276*a71a9546SAutomerger Merge Worker break;
277*a71a9546SAutomerger Merge Worker case O_RANDOM:
278*a71a9546SAutomerger Merge Worker range->flags |= NF_NAT_RANGE_PROTO_RANDOM;
279*a71a9546SAutomerger Merge Worker break;
280*a71a9546SAutomerger Merge Worker case O_RANDOM_FULLY:
281*a71a9546SAutomerger Merge Worker range->flags |= NF_NAT_RANGE_PROTO_RANDOM_FULLY;
282*a71a9546SAutomerger Merge Worker break;
283*a71a9546SAutomerger Merge Worker }
284*a71a9546SAutomerger Merge Worker }
285*a71a9546SAutomerger Merge Worker
NAT_parse(struct xt_option_call * cb)286*a71a9546SAutomerger Merge Worker static void NAT_parse(struct xt_option_call *cb)
287*a71a9546SAutomerger Merge Worker {
288*a71a9546SAutomerger Merge Worker struct nf_nat_ipv4_multi_range_compat *mr = (void *)cb->data;
289*a71a9546SAutomerger Merge Worker const struct ipt_entry *entry = cb->xt_entry;
290*a71a9546SAutomerger Merge Worker struct nf_nat_range2 range = {};
291*a71a9546SAutomerger Merge Worker
292*a71a9546SAutomerger Merge Worker __NAT_parse(cb, entry->ip.proto, &range, AF_INET);
293*a71a9546SAutomerger Merge Worker
294*a71a9546SAutomerger Merge Worker switch (cb->entry->id) {
295*a71a9546SAutomerger Merge Worker case O_TO_DEST:
296*a71a9546SAutomerger Merge Worker case O_TO_SRC:
297*a71a9546SAutomerger Merge Worker mr->range->min_ip = range.min_addr.ip;
298*a71a9546SAutomerger Merge Worker mr->range->max_ip = range.max_addr.ip;
299*a71a9546SAutomerger Merge Worker /* fall through */
300*a71a9546SAutomerger Merge Worker case O_TO_PORTS:
301*a71a9546SAutomerger Merge Worker mr->range->min = range.min_proto;
302*a71a9546SAutomerger Merge Worker mr->range->max = range.max_proto;
303*a71a9546SAutomerger Merge Worker /* fall through */
304*a71a9546SAutomerger Merge Worker case O_PERSISTENT:
305*a71a9546SAutomerger Merge Worker case O_RANDOM:
306*a71a9546SAutomerger Merge Worker case O_RANDOM_FULLY:
307*a71a9546SAutomerger Merge Worker mr->range->flags |= range.flags;
308*a71a9546SAutomerger Merge Worker break;
309*a71a9546SAutomerger Merge Worker }
310*a71a9546SAutomerger Merge Worker }
311*a71a9546SAutomerger Merge Worker
NAT_parse6(struct xt_option_call * cb)312*a71a9546SAutomerger Merge Worker static void NAT_parse6(struct xt_option_call *cb)
313*a71a9546SAutomerger Merge Worker {
314*a71a9546SAutomerger Merge Worker struct nf_nat_range2 range = RANGE2_INIT_FROM_RANGE(cb->data);
315*a71a9546SAutomerger Merge Worker struct nf_nat_range *range_v1 = (void *)cb->data;
316*a71a9546SAutomerger Merge Worker const struct ip6t_entry *entry = cb->xt_entry;
317*a71a9546SAutomerger Merge Worker
318*a71a9546SAutomerger Merge Worker __NAT_parse(cb, entry->ipv6.proto, &range, AF_INET6);
319*a71a9546SAutomerger Merge Worker memcpy(range_v1, &range, sizeof(*range_v1));
320*a71a9546SAutomerger Merge Worker }
321*a71a9546SAutomerger Merge Worker
DNAT_parse_v2(struct xt_option_call * cb)322*a71a9546SAutomerger Merge Worker static void DNAT_parse_v2(struct xt_option_call *cb)
323*a71a9546SAutomerger Merge Worker {
324*a71a9546SAutomerger Merge Worker const struct ipt_entry *entry = cb->xt_entry;
325*a71a9546SAutomerger Merge Worker
326*a71a9546SAutomerger Merge Worker __NAT_parse(cb, entry->ip.proto, cb->data, AF_INET);
327*a71a9546SAutomerger Merge Worker }
328*a71a9546SAutomerger Merge Worker
DNAT_parse6_v2(struct xt_option_call * cb)329*a71a9546SAutomerger Merge Worker static void DNAT_parse6_v2(struct xt_option_call *cb)
330*a71a9546SAutomerger Merge Worker {
331*a71a9546SAutomerger Merge Worker const struct ip6t_entry *entry = cb->xt_entry;
332*a71a9546SAutomerger Merge Worker
333*a71a9546SAutomerger Merge Worker __NAT_parse(cb, entry->ipv6.proto, cb->data, AF_INET6);
334*a71a9546SAutomerger Merge Worker }
335*a71a9546SAutomerger Merge Worker
SNAT_fcheck(struct xt_fcheck_call * cb)336*a71a9546SAutomerger Merge Worker static void SNAT_fcheck(struct xt_fcheck_call *cb)
337*a71a9546SAutomerger Merge Worker {
338*a71a9546SAutomerger Merge Worker struct nf_nat_ipv4_multi_range_compat *mr = cb->data;
339*a71a9546SAutomerger Merge Worker
340*a71a9546SAutomerger Merge Worker mr->rangesize = 1;
341*a71a9546SAutomerger Merge Worker }
342*a71a9546SAutomerger Merge Worker
DNAT_fcheck(struct xt_fcheck_call * cb)343*a71a9546SAutomerger Merge Worker static void DNAT_fcheck(struct xt_fcheck_call *cb)
344*a71a9546SAutomerger Merge Worker {
345*a71a9546SAutomerger Merge Worker struct nf_nat_ipv4_multi_range_compat *mr = cb->data;
346*a71a9546SAutomerger Merge Worker
347*a71a9546SAutomerger Merge Worker mr->rangesize = 1;
348*a71a9546SAutomerger Merge Worker
349*a71a9546SAutomerger Merge Worker if (mr->range[0].flags & NF_NAT_RANGE_PROTO_OFFSET)
350*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
351*a71a9546SAutomerger Merge Worker "Shifted portmap ranges not supported with this kernel");
352*a71a9546SAutomerger Merge Worker }
353*a71a9546SAutomerger Merge Worker
DNAT_fcheck6(struct xt_fcheck_call * cb)354*a71a9546SAutomerger Merge Worker static void DNAT_fcheck6(struct xt_fcheck_call *cb)
355*a71a9546SAutomerger Merge Worker {
356*a71a9546SAutomerger Merge Worker struct nf_nat_range *range = (void *)cb->data;
357*a71a9546SAutomerger Merge Worker
358*a71a9546SAutomerger Merge Worker if (range->flags & NF_NAT_RANGE_PROTO_OFFSET)
359*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
360*a71a9546SAutomerger Merge Worker "Shifted portmap ranges not supported with this kernel");
361*a71a9546SAutomerger Merge Worker }
362*a71a9546SAutomerger Merge Worker
sprint_range(const struct nf_nat_range2 * r,int family)363*a71a9546SAutomerger Merge Worker static char *sprint_range(const struct nf_nat_range2 *r, int family)
364*a71a9546SAutomerger Merge Worker {
365*a71a9546SAutomerger Merge Worker bool brackets = family == AF_INET6 &&
366*a71a9546SAutomerger Merge Worker r->flags & NF_NAT_RANGE_PROTO_SPECIFIED;
367*a71a9546SAutomerger Merge Worker static char buf[INET6_ADDRSTRLEN * 2 + 3 + 6 * 3];
368*a71a9546SAutomerger Merge Worker
369*a71a9546SAutomerger Merge Worker buf[0] = '\0';
370*a71a9546SAutomerger Merge Worker
371*a71a9546SAutomerger Merge Worker if (r->flags & NF_NAT_RANGE_MAP_IPS) {
372*a71a9546SAutomerger Merge Worker if (brackets)
373*a71a9546SAutomerger Merge Worker strcat(buf, "[");
374*a71a9546SAutomerger Merge Worker inet_ntop(family, &r->min_addr,
375*a71a9546SAutomerger Merge Worker buf + strlen(buf), INET6_ADDRSTRLEN);
376*a71a9546SAutomerger Merge Worker if (memcmp(&r->min_addr, &r->max_addr, sizeof(r->min_addr))) {
377*a71a9546SAutomerger Merge Worker strcat(buf, "-");
378*a71a9546SAutomerger Merge Worker inet_ntop(family, &r->max_addr,
379*a71a9546SAutomerger Merge Worker buf + strlen(buf), INET6_ADDRSTRLEN);
380*a71a9546SAutomerger Merge Worker }
381*a71a9546SAutomerger Merge Worker if (brackets)
382*a71a9546SAutomerger Merge Worker strcat(buf, "]");
383*a71a9546SAutomerger Merge Worker }
384*a71a9546SAutomerger Merge Worker if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
385*a71a9546SAutomerger Merge Worker sprintf(buf + strlen(buf), ":%hu",
386*a71a9546SAutomerger Merge Worker ntohs(r->min_proto.tcp.port));
387*a71a9546SAutomerger Merge Worker if (r->max_proto.tcp.port != r->min_proto.tcp.port)
388*a71a9546SAutomerger Merge Worker sprintf(buf + strlen(buf), "-%hu",
389*a71a9546SAutomerger Merge Worker ntohs(r->max_proto.tcp.port));
390*a71a9546SAutomerger Merge Worker if (r->flags & NF_NAT_RANGE_PROTO_OFFSET)
391*a71a9546SAutomerger Merge Worker sprintf(buf + strlen(buf), "/%hu",
392*a71a9546SAutomerger Merge Worker ntohs(r->base_proto.tcp.port));
393*a71a9546SAutomerger Merge Worker }
394*a71a9546SAutomerger Merge Worker return buf;
395*a71a9546SAutomerger Merge Worker }
396*a71a9546SAutomerger Merge Worker
__NAT_print(const struct nf_nat_range2 * r,int family,const char * rangeopt,const char * flag_pfx,bool skip_colon)397*a71a9546SAutomerger Merge Worker static void __NAT_print(const struct nf_nat_range2 *r, int family,
398*a71a9546SAutomerger Merge Worker const char *rangeopt, const char *flag_pfx,
399*a71a9546SAutomerger Merge Worker bool skip_colon)
400*a71a9546SAutomerger Merge Worker {
401*a71a9546SAutomerger Merge Worker char *range_str = sprint_range(r, family);
402*a71a9546SAutomerger Merge Worker
403*a71a9546SAutomerger Merge Worker if (strlen(range_str)) {
404*a71a9546SAutomerger Merge Worker if (range_str[0] == ':' && skip_colon)
405*a71a9546SAutomerger Merge Worker range_str++;
406*a71a9546SAutomerger Merge Worker printf(" %s%s", rangeopt, range_str);
407*a71a9546SAutomerger Merge Worker }
408*a71a9546SAutomerger Merge Worker if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
409*a71a9546SAutomerger Merge Worker printf(" %srandom", flag_pfx);
410*a71a9546SAutomerger Merge Worker if (r->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
411*a71a9546SAutomerger Merge Worker printf(" %srandom-fully", flag_pfx);
412*a71a9546SAutomerger Merge Worker if (r->flags & NF_NAT_RANGE_PERSISTENT)
413*a71a9546SAutomerger Merge Worker printf(" %spersistent", flag_pfx);
414*a71a9546SAutomerger Merge Worker }
415*a71a9546SAutomerger Merge Worker
416*a71a9546SAutomerger Merge Worker static int
__NAT_xlate(struct xt_xlate * xl,const struct nf_nat_range2 * r,int family,const char * tgt)417*a71a9546SAutomerger Merge Worker __NAT_xlate(struct xt_xlate *xl, const struct nf_nat_range2 *r,
418*a71a9546SAutomerger Merge Worker int family, const char *tgt)
419*a71a9546SAutomerger Merge Worker {
420*a71a9546SAutomerger Merge Worker char *range_str = sprint_range(r, family);
421*a71a9546SAutomerger Merge Worker const char *sep = " ";
422*a71a9546SAutomerger Merge Worker
423*a71a9546SAutomerger Merge Worker /* shifted portmap ranges are not supported by nftables */
424*a71a9546SAutomerger Merge Worker if (r->flags & NF_NAT_RANGE_PROTO_OFFSET)
425*a71a9546SAutomerger Merge Worker return 0;
426*a71a9546SAutomerger Merge Worker
427*a71a9546SAutomerger Merge Worker xt_xlate_add(xl, "%s", tgt);
428*a71a9546SAutomerger Merge Worker if (strlen(range_str))
429*a71a9546SAutomerger Merge Worker xt_xlate_add(xl, " to %s", range_str);
430*a71a9546SAutomerger Merge Worker if (r->flags & NF_NAT_RANGE_PROTO_RANDOM) {
431*a71a9546SAutomerger Merge Worker xt_xlate_add(xl, "%srandom", sep);
432*a71a9546SAutomerger Merge Worker sep = ",";
433*a71a9546SAutomerger Merge Worker }
434*a71a9546SAutomerger Merge Worker if (r->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY) {
435*a71a9546SAutomerger Merge Worker xt_xlate_add(xl, "%sfully-random", sep);
436*a71a9546SAutomerger Merge Worker sep = ",";
437*a71a9546SAutomerger Merge Worker }
438*a71a9546SAutomerger Merge Worker if (r->flags & NF_NAT_RANGE_PERSISTENT) {
439*a71a9546SAutomerger Merge Worker xt_xlate_add(xl, "%spersistent", sep);
440*a71a9546SAutomerger Merge Worker sep = ",";
441*a71a9546SAutomerger Merge Worker }
442*a71a9546SAutomerger Merge Worker return 1;
443*a71a9546SAutomerger Merge Worker }
444*a71a9546SAutomerger Merge Worker
445*a71a9546SAutomerger Merge Worker #define PSX_GEN(name, converter, family, \
446*a71a9546SAutomerger Merge Worker print_rangeopt, save_rangeopt, skip_colon, xlate) \
447*a71a9546SAutomerger Merge Worker static void name##_print(const void *ip, const struct xt_entry_target *target, \
448*a71a9546SAutomerger Merge Worker int numeric) \
449*a71a9546SAutomerger Merge Worker { \
450*a71a9546SAutomerger Merge Worker struct nf_nat_range2 range = converter(target->data); \
451*a71a9546SAutomerger Merge Worker \
452*a71a9546SAutomerger Merge Worker __NAT_print(&range, family, print_rangeopt, "", skip_colon); \
453*a71a9546SAutomerger Merge Worker } \
454*a71a9546SAutomerger Merge Worker static void name##_save(const void *ip, const struct xt_entry_target *target) \
455*a71a9546SAutomerger Merge Worker { \
456*a71a9546SAutomerger Merge Worker struct nf_nat_range2 range = converter(target->data); \
457*a71a9546SAutomerger Merge Worker \
458*a71a9546SAutomerger Merge Worker __NAT_print(&range, family, save_rangeopt, "--", skip_colon); \
459*a71a9546SAutomerger Merge Worker } \
460*a71a9546SAutomerger Merge Worker static int name##_xlate(struct xt_xlate *xl, \
461*a71a9546SAutomerger Merge Worker const struct xt_xlate_tg_params *params) \
462*a71a9546SAutomerger Merge Worker { \
463*a71a9546SAutomerger Merge Worker struct nf_nat_range2 range = converter(params->target->data); \
464*a71a9546SAutomerger Merge Worker \
465*a71a9546SAutomerger Merge Worker return __NAT_xlate(xl, &range, family, xlate); \
466*a71a9546SAutomerger Merge Worker }
467*a71a9546SAutomerger Merge Worker
468*a71a9546SAutomerger Merge Worker PSX_GEN(DNAT, RANGE2_INIT_FROM_IPV4_MRC, \
469*a71a9546SAutomerger Merge Worker AF_INET, "to:", "--to-destination ", false, "dnat")
470*a71a9546SAutomerger Merge Worker
471*a71a9546SAutomerger Merge Worker PSX_GEN(DNATv2, *(struct nf_nat_range2 *), \
472*a71a9546SAutomerger Merge Worker AF_INET, "to:", "--to-destination ", false, "dnat")
473*a71a9546SAutomerger Merge Worker
474*a71a9546SAutomerger Merge Worker PSX_GEN(DNAT6, RANGE2_INIT_FROM_RANGE, \
475*a71a9546SAutomerger Merge Worker AF_INET6, "to:", "--to-destination ", false, "dnat")
476*a71a9546SAutomerger Merge Worker
477*a71a9546SAutomerger Merge Worker PSX_GEN(DNAT6v2, *(struct nf_nat_range2 *), \
478*a71a9546SAutomerger Merge Worker AF_INET6, "to:", "--to-destination ", false, "dnat")
479*a71a9546SAutomerger Merge Worker
480*a71a9546SAutomerger Merge Worker PSX_GEN(REDIRECT, RANGE2_INIT_FROM_IPV4_MRC, \
481*a71a9546SAutomerger Merge Worker AF_INET, "redir ports ", "--to-ports ", true, "redirect")
482*a71a9546SAutomerger Merge Worker
483*a71a9546SAutomerger Merge Worker PSX_GEN(REDIRECT6, RANGE2_INIT_FROM_RANGE, \
484*a71a9546SAutomerger Merge Worker AF_INET6, "redir ports ", "--to-ports ", true, "redirect")
485*a71a9546SAutomerger Merge Worker
486*a71a9546SAutomerger Merge Worker PSX_GEN(SNAT, RANGE2_INIT_FROM_IPV4_MRC, \
487*a71a9546SAutomerger Merge Worker AF_INET, "to:", "--to-source ", false, "snat")
488*a71a9546SAutomerger Merge Worker
489*a71a9546SAutomerger Merge Worker PSX_GEN(SNAT6, RANGE2_INIT_FROM_RANGE, \
490*a71a9546SAutomerger Merge Worker AF_INET6, "to:", "--to-source ", false, "snat")
491*a71a9546SAutomerger Merge Worker
492*a71a9546SAutomerger Merge Worker PSX_GEN(MASQUERADE, RANGE2_INIT_FROM_IPV4_MRC, \
493*a71a9546SAutomerger Merge Worker AF_INET, "masq ports: ", "--to-ports ", true, "masquerade")
494*a71a9546SAutomerger Merge Worker
495*a71a9546SAutomerger Merge Worker PSX_GEN(MASQUERADE6, RANGE2_INIT_FROM_RANGE, \
496*a71a9546SAutomerger Merge Worker AF_INET6, "masq ports: ", "--to-ports ", true, "masquerade")
497*a71a9546SAutomerger Merge Worker
498*a71a9546SAutomerger Merge Worker static struct xtables_target nat_tg_reg[] = {
499*a71a9546SAutomerger Merge Worker {
500*a71a9546SAutomerger Merge Worker .name = "SNAT",
501*a71a9546SAutomerger Merge Worker .version = XTABLES_VERSION,
502*a71a9546SAutomerger Merge Worker .family = NFPROTO_IPV4,
503*a71a9546SAutomerger Merge Worker .size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
504*a71a9546SAutomerger Merge Worker .userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
505*a71a9546SAutomerger Merge Worker .help = SNAT_help,
506*a71a9546SAutomerger Merge Worker .x6_parse = NAT_parse,
507*a71a9546SAutomerger Merge Worker .x6_fcheck = SNAT_fcheck,
508*a71a9546SAutomerger Merge Worker .print = SNAT_print,
509*a71a9546SAutomerger Merge Worker .save = SNAT_save,
510*a71a9546SAutomerger Merge Worker .x6_options = SNAT_opts,
511*a71a9546SAutomerger Merge Worker .xlate = SNAT_xlate,
512*a71a9546SAutomerger Merge Worker },
513*a71a9546SAutomerger Merge Worker {
514*a71a9546SAutomerger Merge Worker .name = "DNAT",
515*a71a9546SAutomerger Merge Worker .version = XTABLES_VERSION,
516*a71a9546SAutomerger Merge Worker .family = NFPROTO_IPV4,
517*a71a9546SAutomerger Merge Worker .revision = 0,
518*a71a9546SAutomerger Merge Worker .size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
519*a71a9546SAutomerger Merge Worker .userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
520*a71a9546SAutomerger Merge Worker .help = DNAT_help,
521*a71a9546SAutomerger Merge Worker .print = DNAT_print,
522*a71a9546SAutomerger Merge Worker .save = DNAT_save,
523*a71a9546SAutomerger Merge Worker .x6_parse = NAT_parse,
524*a71a9546SAutomerger Merge Worker .x6_fcheck = DNAT_fcheck,
525*a71a9546SAutomerger Merge Worker .x6_options = DNAT_opts,
526*a71a9546SAutomerger Merge Worker .xlate = DNAT_xlate,
527*a71a9546SAutomerger Merge Worker },
528*a71a9546SAutomerger Merge Worker {
529*a71a9546SAutomerger Merge Worker .name = "MASQUERADE",
530*a71a9546SAutomerger Merge Worker .version = XTABLES_VERSION,
531*a71a9546SAutomerger Merge Worker .family = NFPROTO_IPV4,
532*a71a9546SAutomerger Merge Worker .size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
533*a71a9546SAutomerger Merge Worker .userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
534*a71a9546SAutomerger Merge Worker .help = MASQUERADE_help,
535*a71a9546SAutomerger Merge Worker .x6_parse = NAT_parse,
536*a71a9546SAutomerger Merge Worker .x6_fcheck = SNAT_fcheck,
537*a71a9546SAutomerger Merge Worker .print = MASQUERADE_print,
538*a71a9546SAutomerger Merge Worker .save = MASQUERADE_save,
539*a71a9546SAutomerger Merge Worker .x6_options = MASQUERADE_opts,
540*a71a9546SAutomerger Merge Worker .xlate = MASQUERADE_xlate,
541*a71a9546SAutomerger Merge Worker },
542*a71a9546SAutomerger Merge Worker {
543*a71a9546SAutomerger Merge Worker .name = "MASQUERADE",
544*a71a9546SAutomerger Merge Worker .version = XTABLES_VERSION,
545*a71a9546SAutomerger Merge Worker .family = NFPROTO_IPV6,
546*a71a9546SAutomerger Merge Worker .size = XT_ALIGN(sizeof(struct nf_nat_range)),
547*a71a9546SAutomerger Merge Worker .userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)),
548*a71a9546SAutomerger Merge Worker .help = MASQUERADE_help,
549*a71a9546SAutomerger Merge Worker .x6_parse = NAT_parse6,
550*a71a9546SAutomerger Merge Worker .print = MASQUERADE6_print,
551*a71a9546SAutomerger Merge Worker .save = MASQUERADE6_save,
552*a71a9546SAutomerger Merge Worker .x6_options = MASQUERADE_opts,
553*a71a9546SAutomerger Merge Worker .xlate = MASQUERADE6_xlate,
554*a71a9546SAutomerger Merge Worker },
555*a71a9546SAutomerger Merge Worker {
556*a71a9546SAutomerger Merge Worker .name = "REDIRECT",
557*a71a9546SAutomerger Merge Worker .version = XTABLES_VERSION,
558*a71a9546SAutomerger Merge Worker .family = NFPROTO_IPV4,
559*a71a9546SAutomerger Merge Worker .revision = 0,
560*a71a9546SAutomerger Merge Worker .size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
561*a71a9546SAutomerger Merge Worker .userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
562*a71a9546SAutomerger Merge Worker .help = REDIRECT_help,
563*a71a9546SAutomerger Merge Worker .print = REDIRECT_print,
564*a71a9546SAutomerger Merge Worker .save = REDIRECT_save,
565*a71a9546SAutomerger Merge Worker .x6_parse = NAT_parse,
566*a71a9546SAutomerger Merge Worker .x6_fcheck = DNAT_fcheck,
567*a71a9546SAutomerger Merge Worker .x6_options = REDIRECT_opts,
568*a71a9546SAutomerger Merge Worker .xlate = REDIRECT_xlate,
569*a71a9546SAutomerger Merge Worker },
570*a71a9546SAutomerger Merge Worker {
571*a71a9546SAutomerger Merge Worker .name = "SNAT",
572*a71a9546SAutomerger Merge Worker .version = XTABLES_VERSION,
573*a71a9546SAutomerger Merge Worker .family = NFPROTO_IPV6,
574*a71a9546SAutomerger Merge Worker .revision = 1,
575*a71a9546SAutomerger Merge Worker .size = XT_ALIGN(sizeof(struct nf_nat_range)),
576*a71a9546SAutomerger Merge Worker .userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)),
577*a71a9546SAutomerger Merge Worker .help = SNAT_help,
578*a71a9546SAutomerger Merge Worker .x6_parse = NAT_parse6,
579*a71a9546SAutomerger Merge Worker .print = SNAT6_print,
580*a71a9546SAutomerger Merge Worker .save = SNAT6_save,
581*a71a9546SAutomerger Merge Worker .x6_options = SNAT_opts,
582*a71a9546SAutomerger Merge Worker .xlate = SNAT6_xlate,
583*a71a9546SAutomerger Merge Worker },
584*a71a9546SAutomerger Merge Worker {
585*a71a9546SAutomerger Merge Worker .name = "DNAT",
586*a71a9546SAutomerger Merge Worker .version = XTABLES_VERSION,
587*a71a9546SAutomerger Merge Worker .family = NFPROTO_IPV6,
588*a71a9546SAutomerger Merge Worker .revision = 1,
589*a71a9546SAutomerger Merge Worker .size = XT_ALIGN(sizeof(struct nf_nat_range)),
590*a71a9546SAutomerger Merge Worker .userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)),
591*a71a9546SAutomerger Merge Worker .help = DNAT_help,
592*a71a9546SAutomerger Merge Worker .print = DNAT6_print,
593*a71a9546SAutomerger Merge Worker .save = DNAT6_save,
594*a71a9546SAutomerger Merge Worker .x6_parse = NAT_parse6,
595*a71a9546SAutomerger Merge Worker .x6_fcheck = DNAT_fcheck6,
596*a71a9546SAutomerger Merge Worker .x6_options = DNAT_opts,
597*a71a9546SAutomerger Merge Worker .xlate = DNAT6_xlate,
598*a71a9546SAutomerger Merge Worker },
599*a71a9546SAutomerger Merge Worker {
600*a71a9546SAutomerger Merge Worker .name = "REDIRECT",
601*a71a9546SAutomerger Merge Worker .version = XTABLES_VERSION,
602*a71a9546SAutomerger Merge Worker .family = NFPROTO_IPV6,
603*a71a9546SAutomerger Merge Worker .size = XT_ALIGN(sizeof(struct nf_nat_range)),
604*a71a9546SAutomerger Merge Worker .userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)),
605*a71a9546SAutomerger Merge Worker .help = REDIRECT_help,
606*a71a9546SAutomerger Merge Worker .print = REDIRECT6_print,
607*a71a9546SAutomerger Merge Worker .save = REDIRECT6_save,
608*a71a9546SAutomerger Merge Worker .x6_parse = NAT_parse6,
609*a71a9546SAutomerger Merge Worker .x6_fcheck = DNAT_fcheck6,
610*a71a9546SAutomerger Merge Worker .x6_options = REDIRECT_opts,
611*a71a9546SAutomerger Merge Worker .xlate = REDIRECT6_xlate,
612*a71a9546SAutomerger Merge Worker },
613*a71a9546SAutomerger Merge Worker {
614*a71a9546SAutomerger Merge Worker .name = "DNAT",
615*a71a9546SAutomerger Merge Worker .version = XTABLES_VERSION,
616*a71a9546SAutomerger Merge Worker .family = NFPROTO_IPV4,
617*a71a9546SAutomerger Merge Worker .revision = 2,
618*a71a9546SAutomerger Merge Worker .size = XT_ALIGN(sizeof(struct nf_nat_range2)),
619*a71a9546SAutomerger Merge Worker .userspacesize = XT_ALIGN(sizeof(struct nf_nat_range2)),
620*a71a9546SAutomerger Merge Worker .help = DNAT_help_v2,
621*a71a9546SAutomerger Merge Worker .print = DNATv2_print,
622*a71a9546SAutomerger Merge Worker .save = DNATv2_save,
623*a71a9546SAutomerger Merge Worker .x6_parse = DNAT_parse_v2,
624*a71a9546SAutomerger Merge Worker .x6_options = DNAT_opts,
625*a71a9546SAutomerger Merge Worker .xlate = DNATv2_xlate,
626*a71a9546SAutomerger Merge Worker },
627*a71a9546SAutomerger Merge Worker {
628*a71a9546SAutomerger Merge Worker .name = "DNAT",
629*a71a9546SAutomerger Merge Worker .version = XTABLES_VERSION,
630*a71a9546SAutomerger Merge Worker .family = NFPROTO_IPV6,
631*a71a9546SAutomerger Merge Worker .revision = 2,
632*a71a9546SAutomerger Merge Worker .size = XT_ALIGN(sizeof(struct nf_nat_range2)),
633*a71a9546SAutomerger Merge Worker .userspacesize = XT_ALIGN(sizeof(struct nf_nat_range2)),
634*a71a9546SAutomerger Merge Worker .help = DNAT_help_v2,
635*a71a9546SAutomerger Merge Worker .print = DNAT6v2_print,
636*a71a9546SAutomerger Merge Worker .save = DNAT6v2_save,
637*a71a9546SAutomerger Merge Worker .x6_parse = DNAT_parse6_v2,
638*a71a9546SAutomerger Merge Worker .x6_options = DNAT_opts,
639*a71a9546SAutomerger Merge Worker .xlate = DNAT6v2_xlate,
640*a71a9546SAutomerger Merge Worker },
641*a71a9546SAutomerger Merge Worker };
642*a71a9546SAutomerger Merge Worker
_init(void)643*a71a9546SAutomerger Merge Worker void _init(void)
644*a71a9546SAutomerger Merge Worker {
645*a71a9546SAutomerger Merge Worker xtables_register_targets(nat_tg_reg, ARRAY_SIZE(nat_tg_reg));
646*a71a9546SAutomerger Merge Worker }
647