blob: 16e1842b741b3ac49dafa6b90b2015424d6185b9 [file] [log] [blame]
Bart De Schuymer1abc55d2002-06-01 19:23:47 +00001#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
Bart De Schuymer41830412002-06-05 19:41:28 +00004#include <netinet/ether.h>
Bart De Schuymer1abc55d2002-06-01 19:23:47 +00005#include <getopt.h>
6#include "../include/ebtables_u.h"
7#include <linux/netfilter_bridge/ebt_nat.h>
8
Bart De Schuymer9cfd6542002-08-13 16:08:08 +00009static int to_source_supplied, to_dest_supplied;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000010
11#define NAT_S '1'
12#define NAT_D '1'
13#define NAT_S_TARGET '2'
14#define NAT_D_TARGET '2'
15static struct option opts_s[] =
16{
17 { "to-source" , required_argument, 0, NAT_S },
18 { "to-src" , required_argument, 0, NAT_S },
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000019 { "snat-target" , required_argument, 0, NAT_S_TARGET },
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000020 { 0 }
21};
22
23static struct option opts_d[] =
24{
25 { "to-destination", required_argument, 0, NAT_D },
26 { "to-dst" , required_argument, 0, NAT_D },
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000027 { "dnat-target" , required_argument, 0, NAT_D_TARGET },
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000028 { 0 }
29};
30
31static void print_help_s()
32{
33 printf(
34 "snat options:\n"
35 " --to-src address : MAC address to map source to\n"
Bart De Schuymerb26649e2002-07-25 14:51:54 +000036 " --snat-target target : ACCEPT, DROP, RETURN or CONTINUE\n");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000037}
38
39static void print_help_d()
40{
41 printf(
42 "dnat options:\n"
43 " --to-dst address : MAC address to map destination to\n"
Bart De Schuymerb26649e2002-07-25 14:51:54 +000044 " --dnat-target target : ACCEPT, DROP, RETURN or CONTINUE\n");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000045}
46
47static void init_s(struct ebt_entry_target *target)
48{
49 struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
50
51 to_source_supplied = 0;
52 natinfo->target = EBT_ACCEPT;
Bart De Schuymer2f0d7482003-06-04 06:23:49 +000053 return;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000054}
55
56static void init_d(struct ebt_entry_target *target)
57{
58 struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
59
60 to_dest_supplied = 0;
61 natinfo->target = EBT_ACCEPT;
62 return;
63}
64
65#define OPT_SNAT 0x01
66#define OPT_SNAT_TARGET 0x02
67static int parse_s(int c, char **argv, int argc,
68 const struct ebt_u_entry *entry, unsigned int *flags,
69 struct ebt_entry_target **target)
70{
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000071 struct ebt_nat_info *natinfo = (struct ebt_nat_info *)(*target)->data;
Bart De Schuymer41830412002-06-05 19:41:28 +000072 struct ether_addr *addr;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000073
74 switch (c) {
75 case NAT_S:
Bart De Schuymer8339ff12004-01-14 20:05:27 +000076 ebt_check_option(flags, OPT_SNAT);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000077 to_source_supplied = 1;
Bart De Schuymer41830412002-06-05 19:41:28 +000078 if (!(addr = ether_aton(optarg)))
Bart De Schuymerb26649e2002-07-25 14:51:54 +000079 print_error("Problem with specified --to-source mac");
Bart De Schuymer41830412002-06-05 19:41:28 +000080 memcpy(natinfo->mac, addr, ETH_ALEN);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000081 break;
82 case NAT_S_TARGET:
Bart De Schuymer8339ff12004-01-14 20:05:27 +000083 ebt_check_option(flags, OPT_SNAT_TARGET);
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000084 if (FILL_TARGET(optarg, natinfo->target))
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000085 print_error("Illegal --snat-target target");
86 break;
87 default:
88 return 0;
89 }
90 return 1;
91}
92
93#define OPT_DNAT 0x01
94#define OPT_DNAT_TARGET 0x02
95static int parse_d(int c, char **argv, int argc,
96 const struct ebt_u_entry *entry, unsigned int *flags,
97 struct ebt_entry_target **target)
98{
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000099 struct ebt_nat_info *natinfo = (struct ebt_nat_info *)(*target)->data;
Bart De Schuymer41830412002-06-05 19:41:28 +0000100 struct ether_addr *addr;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000101
102 switch (c) {
103 case NAT_D:
Bart De Schuymer8339ff12004-01-14 20:05:27 +0000104 ebt_check_option(flags, OPT_DNAT);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000105 to_dest_supplied = 1;
Bart De Schuymer41830412002-06-05 19:41:28 +0000106 if (!(addr = ether_aton(optarg)))
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000107 print_error("Problem with specified "
Bart De Schuymerb26649e2002-07-25 14:51:54 +0000108 "--to-destination mac");
Bart De Schuymer41830412002-06-05 19:41:28 +0000109 memcpy(natinfo->mac, addr, ETH_ALEN);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000110 break;
111 case NAT_D_TARGET:
Bart De Schuymer8339ff12004-01-14 20:05:27 +0000112 ebt_check_option(flags, OPT_DNAT_TARGET);
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000113 if (FILL_TARGET(optarg, natinfo->target))
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000114 print_error("Illegal --dnat-target target");
115 break;
116 default:
117 return 0;
118 }
119 return 1;
120}
121
122static void final_check_s(const struct ebt_u_entry *entry,
Bart De Schuymer7b9aaeb2002-06-23 20:38:34 +0000123 const struct ebt_entry_target *target, const char *name,
Bart De Schuymerc9b52932002-08-24 13:26:34 +0000124 unsigned int hookmask, unsigned int time)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000125{
Bart De Schuymerb26649e2002-07-25 14:51:54 +0000126 struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
127
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000128 if (BASE_CHAIN && natinfo->target == EBT_RETURN)
Bart De Schuymerb26649e2002-07-25 14:51:54 +0000129 print_error("--snat-target RETURN not allowed on base chain");
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000130 CLEAR_BASE_CHAIN_BIT;
Bart De Schuymerc9b52932002-08-24 13:26:34 +0000131 if ((hookmask & ~(1 << NF_BR_POST_ROUTING)) || strcmp(name, "nat"))
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000132 print_error("Wrong chain for snat");
Bart De Schuymer7b9aaeb2002-06-23 20:38:34 +0000133 if (time == 0 && to_source_supplied == 0)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000134 print_error("No snat address supplied");
135}
136
137static void final_check_d(const struct ebt_u_entry *entry,
Bart De Schuymer7b9aaeb2002-06-23 20:38:34 +0000138 const struct ebt_entry_target *target, const char *name,
Bart De Schuymerc9b52932002-08-24 13:26:34 +0000139 unsigned int hookmask, unsigned int time)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000140{
Bart De Schuymerb26649e2002-07-25 14:51:54 +0000141 struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
142
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000143 if (BASE_CHAIN && natinfo->target == EBT_RETURN)
Bart De Schuymerb26649e2002-07-25 14:51:54 +0000144 print_error("--dnat-target RETURN not allowed on base chain");
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000145 CLEAR_BASE_CHAIN_BIT;
Bart De Schuymerc9b52932002-08-24 13:26:34 +0000146 if (((hookmask & ~((1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_LOCAL_OUT)))
147 || strcmp(name, "nat")) &&
148 ((hookmask & ~(1 << NF_BR_BROUTING)) || strcmp(name, "broute")))
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000149 print_error("Wrong chain for dnat");
Bart De Schuymer7b9aaeb2002-06-23 20:38:34 +0000150 if (time == 0 && to_dest_supplied == 0)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000151 print_error("No dnat address supplied");
152}
153
154static void print_s(const struct ebt_u_entry *entry,
155 const struct ebt_entry_target *target)
156{
157 struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000158
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000159 printf("--to-src ");
Bart De Schuymer8339ff12004-01-14 20:05:27 +0000160 ebt_print_mac(natinfo->mac);
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000161 printf(" --snat-target %s", TARGET_NAME(natinfo->target));
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000162}
163
164static void print_d(const struct ebt_u_entry *entry,
165 const struct ebt_entry_target *target)
166{
167 struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000168
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000169 printf("--to-dst ");
Bart De Schuymer8339ff12004-01-14 20:05:27 +0000170 ebt_print_mac(natinfo->mac);
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000171 printf(" --dnat-target %s", TARGET_NAME(natinfo->target));
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000172}
173
174static int compare(const struct ebt_entry_target *t1,
175 const struct ebt_entry_target *t2)
176{
177 struct ebt_nat_info *natinfo1 = (struct ebt_nat_info *)t1->data;
178 struct ebt_nat_info *natinfo2 = (struct ebt_nat_info *)t2->data;
179
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000180 return !memcmp(natinfo1->mac, natinfo2->mac, sizeof(natinfo1->mac)) &&
181 natinfo1->target == natinfo2->target;
182}
183
184static struct ebt_u_target snat_target =
185{
Bart De Schuymer7cf1cca2003-08-30 16:20:19 +0000186 .name = EBT_SNAT_TARGET,
187 .size = sizeof(struct ebt_nat_info),
188 .help = print_help_s,
189 .init = init_s,
190 .parse = parse_s,
191 .final_check = final_check_s,
192 .print = print_s,
193 .compare = compare,
194 .extra_ops = opts_s,
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000195};
196
197static struct ebt_u_target dnat_target =
198{
Bart De Schuymer7cf1cca2003-08-30 16:20:19 +0000199 .name = EBT_DNAT_TARGET,
200 .size = sizeof(struct ebt_nat_info),
201 .help = print_help_d,
202 .init = init_d,
203 .parse = parse_d,
204 .final_check = final_check_d,
205 .print = print_d,
206 .compare = compare,
207 .extra_ops = opts_d,
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000208};
209
210static void _init(void) __attribute__ ((constructor));
211static void _init(void)
212{
Bart De Schuymer8339ff12004-01-14 20:05:27 +0000213 ebt_register_target(&snat_target);
214 ebt_register_target(&dnat_target);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000215}