blob: 25b12ca92d71bbf8b6b4997fd49c651fde13e914 [file] [log] [blame]
Bart De Schuymer1abc55d2002-06-01 19:23:47 +00001#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <sys/socket.h>
5#include <netinet/in.h>
Bart De Schuymer41830412002-06-05 19:41:28 +00006#include <netinet/ether.h>
Bart De Schuymer1abc55d2002-06-01 19:23:47 +00007#include <getopt.h>
8#include "../include/ebtables_u.h"
9#include <linux/netfilter_bridge/ebt_nat.h>
10
11extern char *standard_targets[NUM_STANDARD_TARGETS];
12
13int to_source_supplied, to_dest_supplied;
14
15#define NAT_S '1'
16#define NAT_D '1'
17#define NAT_S_TARGET '2'
18#define NAT_D_TARGET '2'
19static struct option opts_s[] =
20{
21 { "to-source" , required_argument, 0, NAT_S },
22 { "to-src" , required_argument, 0, NAT_S },
23 { "snat-target" , required_argument, 0, NAT_S_TARGET },
24 { 0 }
25};
26
27static struct option opts_d[] =
28{
29 { "to-destination", required_argument, 0, NAT_D },
30 { "to-dst" , required_argument, 0, NAT_D },
31 { "dnat-target" , required_argument, 0, NAT_D_TARGET },
32 { 0 }
33};
34
35static void print_help_s()
36{
37 printf(
38 "snat options:\n"
39 " --to-src address : MAC address to map source to\n"
Bart De Schuymerb26649e2002-07-25 14:51:54 +000040 " --snat-target target : ACCEPT, DROP, RETURN or CONTINUE\n");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000041}
42
43static void print_help_d()
44{
45 printf(
46 "dnat options:\n"
47 " --to-dst address : MAC address to map destination to\n"
Bart De Schuymerb26649e2002-07-25 14:51:54 +000048 " --dnat-target target : ACCEPT, DROP, RETURN or CONTINUE\n");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000049}
50
51static void init_s(struct ebt_entry_target *target)
52{
53 struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
54
55 to_source_supplied = 0;
56 natinfo->target = EBT_ACCEPT;
57 return;
58}
59
60static void init_d(struct ebt_entry_target *target)
61{
62 struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
63
64 to_dest_supplied = 0;
65 natinfo->target = EBT_ACCEPT;
66 return;
67}
68
69#define OPT_SNAT 0x01
70#define OPT_SNAT_TARGET 0x02
71static int parse_s(int c, char **argv, int argc,
72 const struct ebt_u_entry *entry, unsigned int *flags,
73 struct ebt_entry_target **target)
74{
75 int i;
76 struct ebt_nat_info *natinfo = (struct ebt_nat_info *)(*target)->data;
Bart De Schuymer41830412002-06-05 19:41:28 +000077 struct ether_addr *addr;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000078
79 switch (c) {
80 case NAT_S:
81 check_option(flags, OPT_SNAT);
82 to_source_supplied = 1;
Bart De Schuymer41830412002-06-05 19:41:28 +000083 if (!(addr = ether_aton(optarg)))
Bart De Schuymerb26649e2002-07-25 14:51:54 +000084 print_error("Problem with specified --to-source mac");
Bart De Schuymer41830412002-06-05 19:41:28 +000085 memcpy(natinfo->mac, addr, ETH_ALEN);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000086 break;
87 case NAT_S_TARGET:
88 check_option(flags, OPT_SNAT_TARGET);
89 for (i = 0; i < NUM_STANDARD_TARGETS; i++)
90 if (!strcmp(optarg, standard_targets[i])) {
Bart De Schuymer25c741d2002-06-23 18:54:34 +000091 natinfo->target = -i - 1;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000092 break;
93 }
94 if (i == NUM_STANDARD_TARGETS)
95 print_error("Illegal --snat-target target");
96 break;
97 default:
98 return 0;
99 }
100 return 1;
101}
102
103#define OPT_DNAT 0x01
104#define OPT_DNAT_TARGET 0x02
105static int parse_d(int c, char **argv, int argc,
106 const struct ebt_u_entry *entry, unsigned int *flags,
107 struct ebt_entry_target **target)
108{
109 int i;
110 struct ebt_nat_info *natinfo = (struct ebt_nat_info *)(*target)->data;
Bart De Schuymer41830412002-06-05 19:41:28 +0000111 struct ether_addr *addr;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000112
113 switch (c) {
114 case NAT_D:
115 check_option(flags, OPT_DNAT);
116 to_dest_supplied = 1;
Bart De Schuymer41830412002-06-05 19:41:28 +0000117 if (!(addr = ether_aton(optarg)))
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000118 print_error("Problem with specified "
Bart De Schuymerb26649e2002-07-25 14:51:54 +0000119 "--to-destination mac");
Bart De Schuymer41830412002-06-05 19:41:28 +0000120 memcpy(natinfo->mac, addr, ETH_ALEN);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000121 break;
122 case NAT_D_TARGET:
123 check_option(flags, OPT_DNAT_TARGET);
124 for (i = 0; i < NUM_STANDARD_TARGETS; i++)
125 if (!strcmp(optarg, standard_targets[i])) {
Bart De Schuymer25c741d2002-06-23 18:54:34 +0000126 natinfo->target = -i - 1;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000127 break;
128 }
129 if (i == NUM_STANDARD_TARGETS)
130 print_error("Illegal --dnat-target target");
131 break;
132 default:
133 return 0;
134 }
135 return 1;
136}
137
138static void final_check_s(const struct ebt_u_entry *entry,
Bart De Schuymer7b9aaeb2002-06-23 20:38:34 +0000139 const struct ebt_entry_target *target, const char *name,
140 unsigned int hook_mask, unsigned int time)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000141{
Bart De Schuymerb26649e2002-07-25 14:51:54 +0000142 struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
143
144 if ((hook_mask & (1 << NF_BR_NUMHOOKS)) && natinfo->target == EBT_RETURN)
145 print_error("--snat-target RETURN not allowed on base chain");
146 hook_mask &= ~(1 << NF_BR_NUMHOOKS);
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000147 if (!(hook_mask & (1 << NF_BR_POST_ROUTING)) || strcmp(name, "nat"))
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000148 print_error("Wrong chain for snat");
Bart De Schuymer7b9aaeb2002-06-23 20:38:34 +0000149 if (time == 0 && to_source_supplied == 0)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000150 print_error("No snat address supplied");
151}
152
153static void final_check_d(const struct ebt_u_entry *entry,
Bart De Schuymer7b9aaeb2002-06-23 20:38:34 +0000154 const struct ebt_entry_target *target, const char *name,
155 unsigned int hook_mask, unsigned int time)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000156{
Bart De Schuymerb26649e2002-07-25 14:51:54 +0000157 struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
158
159 if ((hook_mask & (1 << NF_BR_NUMHOOKS)) && natinfo->target == EBT_RETURN)
160 print_error("--dnat-target RETURN not allowed on base chain");
161 hook_mask &= ~(1 << NF_BR_NUMHOOKS);
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000162 if (((hook_mask & ~((1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_LOCAL_OUT))) ||
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000163 strcmp(name, "nat")) &&
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000164 ((hook_mask & ~(1 << NF_BR_BROUTING)) || strcmp(name, "broute")))
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000165 print_error("Wrong chain for dnat");
Bart De Schuymer7b9aaeb2002-06-23 20:38:34 +0000166 if (time == 0 && to_dest_supplied == 0)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000167 print_error("No dnat address supplied");
168}
169
170static void print_s(const struct ebt_u_entry *entry,
171 const struct ebt_entry_target *target)
172{
173 struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000174
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000175 printf("--to-src ");
Bart De Schuymer41830412002-06-05 19:41:28 +0000176 printf("%s", ether_ntoa((struct ether_addr *)natinfo->mac));
Bart De Schuymer25c741d2002-06-23 18:54:34 +0000177 printf(" --snat-target %s", standard_targets[-natinfo->target - 1]);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000178}
179
180static void print_d(const struct ebt_u_entry *entry,
181 const struct ebt_entry_target *target)
182{
183 struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000184
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000185 printf("--to-dst ");
Bart De Schuymer41830412002-06-05 19:41:28 +0000186 printf("%s", ether_ntoa((struct ether_addr *)natinfo->mac));
Bart De Schuymer25c741d2002-06-23 18:54:34 +0000187 printf(" --dnat-target %s", standard_targets[-natinfo->target - 1]);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000188}
189
190static int compare(const struct ebt_entry_target *t1,
191 const struct ebt_entry_target *t2)
192{
193 struct ebt_nat_info *natinfo1 = (struct ebt_nat_info *)t1->data;
194 struct ebt_nat_info *natinfo2 = (struct ebt_nat_info *)t2->data;
195
196
197 return !memcmp(natinfo1->mac, natinfo2->mac, sizeof(natinfo1->mac)) &&
198 natinfo1->target == natinfo2->target;
199}
200
201static struct ebt_u_target snat_target =
202{
203 EBT_SNAT_TARGET,
204 sizeof(struct ebt_nat_info),
205 print_help_s,
206 init_s,
207 parse_s,
208 final_check_s,
209 print_s,
210 compare,
211 opts_s,
212};
213
214static struct ebt_u_target dnat_target =
215{
216 EBT_DNAT_TARGET,
217 sizeof(struct ebt_nat_info),
218 print_help_d,
219 init_d,
220 parse_d,
221 final_check_d,
222 print_d,
223 compare,
224 opts_d,
225};
226
227static void _init(void) __attribute__ ((constructor));
228static void _init(void)
229{
230 register_target(&snat_target);
231 register_target(&dnat_target);
232}