4 * Bart De Schuymer <bdschuym@pandora.be>
13 #include "../include/ebtables_u.h"
14 #include <netinet/ether.h>
15 #include <linux/netfilter_bridge/ebt_nat.h>
17 static int to_source_supplied
, to_dest_supplied
;
21 #define NAT_S_TARGET '2'
22 #define NAT_D_TARGET '2'
24 static struct option opts_s
[] =
26 { "to-source" , required_argument
, 0, NAT_S
},
27 { "to-src" , required_argument
, 0, NAT_S
},
28 { "snat-target" , required_argument
, 0, NAT_S_TARGET
},
29 { "snat-arp" , no_argument
, 0, NAT_S_ARP
},
33 static struct option opts_d
[] =
35 { "to-destination", required_argument
, 0, NAT_D
},
36 { "to-dst" , required_argument
, 0, NAT_D
},
37 { "dnat-target" , required_argument
, 0, NAT_D_TARGET
},
41 static void print_help_s()
45 " --to-src address : MAC address to map source to\n"
46 " --snat-target target : ACCEPT, DROP, RETURN or CONTINUE\n"
47 " --snat-arp : also change src address in arp msg\n");
50 static void print_help_d()
54 " --to-dst address : MAC address to map destination to\n"
55 " --dnat-target target : ACCEPT, DROP, RETURN or CONTINUE\n");
58 static void init_s(struct ebt_entry_target
*target
)
60 struct ebt_nat_info
*natinfo
= (struct ebt_nat_info
*)target
->data
;
62 to_source_supplied
= 0;
63 natinfo
->target
= EBT_ACCEPT
;
67 static void init_d(struct ebt_entry_target
*target
)
69 struct ebt_nat_info
*natinfo
= (struct ebt_nat_info
*)target
->data
;
72 natinfo
->target
= EBT_ACCEPT
;
77 #define OPT_SNAT_TARGET 0x02
78 #define OPT_SNAT_ARP 0x04
79 static int parse_s(int c
, char **argv
, int argc
,
80 const struct ebt_u_entry
*entry
, unsigned int *flags
,
81 struct ebt_entry_target
**target
)
83 struct ebt_nat_info
*natinfo
= (struct ebt_nat_info
*)(*target
)->data
;
84 struct ether_addr
*addr
;
88 ebt_check_option2(flags
, OPT_SNAT
);
89 to_source_supplied
= 1;
90 if (!(addr
= ether_aton(optarg
)))
91 ebt_print_error2("Problem with specified --to-source mac");
92 memcpy(natinfo
->mac
, addr
, ETH_ALEN
);
96 ebt_check_option2(flags
, OPT_SNAT_TARGET
);
97 if (FILL_TARGET(optarg
, tmp
))
98 ebt_print_error2("Illegal --snat-target target");
99 natinfo
->target
= (natinfo
->target
& ~EBT_VERDICT_BITS
) | (tmp
& EBT_VERDICT_BITS
);
103 ebt_check_option2(flags
, OPT_SNAT_ARP
);
104 natinfo
->target
^= NAT_ARP_BIT
;
112 #define OPT_DNAT 0x01
113 #define OPT_DNAT_TARGET 0x02
114 static int parse_d(int c
, char **argv
, int argc
,
115 const struct ebt_u_entry
*entry
, unsigned int *flags
,
116 struct ebt_entry_target
**target
)
118 struct ebt_nat_info
*natinfo
= (struct ebt_nat_info
*)(*target
)->data
;
119 struct ether_addr
*addr
;
123 ebt_check_option2(flags
, OPT_DNAT
);
124 to_dest_supplied
= 1;
125 if (!(addr
= ether_aton(optarg
)))
126 ebt_print_error2("Problem with specified --to-destination mac");
127 memcpy(natinfo
->mac
, addr
, ETH_ALEN
);
130 ebt_check_option2(flags
, OPT_DNAT_TARGET
);
131 if (FILL_TARGET(optarg
, natinfo
->target
))
132 ebt_print_error2("Illegal --dnat-target target");
140 static void final_check_s(const struct ebt_u_entry
*entry
,
141 const struct ebt_entry_target
*target
, const char *name
,
142 unsigned int hookmask
, unsigned int time
)
144 struct ebt_nat_info
*natinfo
= (struct ebt_nat_info
*)target
->data
;
146 if (BASE_CHAIN
&& (natinfo
->target
| ~EBT_VERDICT_BITS
) == EBT_RETURN
) {
147 ebt_print_error("--snat-target RETURN not allowed on base chain");
150 CLEAR_BASE_CHAIN_BIT
;
151 if ((hookmask
& ~(1 << NF_BR_POST_ROUTING
)) || strcmp(name
, "nat")) {
152 ebt_print_error("Wrong chain for snat");
153 } else if (time
== 0 && to_source_supplied
== 0)
154 ebt_print_error("No snat address supplied");
157 static void final_check_d(const struct ebt_u_entry
*entry
,
158 const struct ebt_entry_target
*target
, const char *name
,
159 unsigned int hookmask
, unsigned int time
)
161 struct ebt_nat_info
*natinfo
= (struct ebt_nat_info
*)target
->data
;
163 if (BASE_CHAIN
&& natinfo
->target
== EBT_RETURN
) {
164 ebt_print_error("--dnat-target RETURN not allowed on base chain");
167 CLEAR_BASE_CHAIN_BIT
;
168 if (((hookmask
& ~((1 << NF_BR_PRE_ROUTING
) | (1 << NF_BR_LOCAL_OUT
)))
169 || strcmp(name
, "nat")) &&
170 ((hookmask
& ~(1 << NF_BR_BROUTING
)) || strcmp(name
, "broute"))) {
171 ebt_print_error("Wrong chain for dnat");
172 } else if (time
== 0 && to_dest_supplied
== 0)
173 ebt_print_error("No dnat address supplied");
176 static void print_s(const struct ebt_u_entry
*entry
,
177 const struct ebt_entry_target
*target
)
179 struct ebt_nat_info
*natinfo
= (struct ebt_nat_info
*)target
->data
;
182 ebt_print_mac(natinfo
->mac
);
183 if (!(natinfo
->target
&NAT_ARP_BIT
))
184 printf(" --snat-arp");
185 printf(" --snat-target %s", TARGET_NAME((natinfo
->target
|~EBT_VERDICT_BITS
)));
188 static void print_d(const struct ebt_u_entry
*entry
,
189 const struct ebt_entry_target
*target
)
191 struct ebt_nat_info
*natinfo
= (struct ebt_nat_info
*)target
->data
;
194 ebt_print_mac(natinfo
->mac
);
195 printf(" --dnat-target %s", TARGET_NAME(natinfo
->target
));
198 static int compare(const struct ebt_entry_target
*t1
,
199 const struct ebt_entry_target
*t2
)
201 struct ebt_nat_info
*natinfo1
= (struct ebt_nat_info
*)t1
->data
;
202 struct ebt_nat_info
*natinfo2
= (struct ebt_nat_info
*)t2
->data
;
204 return !memcmp(natinfo1
->mac
, natinfo2
->mac
, sizeof(natinfo1
->mac
)) &&
205 natinfo1
->target
== natinfo2
->target
;
208 static struct ebt_u_target snat_target
=
211 .size
= sizeof(struct ebt_nat_info
),
212 .help
= print_help_s
,
215 .final_check
= final_check_s
,
221 static struct ebt_u_target dnat_target
=
224 .size
= sizeof(struct ebt_nat_info
),
225 .help
= print_help_d
,
228 .final_check
= final_check_d
,
236 ebt_register_target(&snat_target
);
237 ebt_register_target(&dnat_target
);