2 * fwd - OpenWrt firewall daemon - iptables rule set
4 * Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
6 * The fwd program is free software: you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License version 2
8 * as published by the Free Software Foundation.
10 * The fwd program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with the fwd program. If not, see http://www.gnu.org/licenses/.
22 #include "fwd_rules.h"
23 #include "fwd_xtables.h"
26 /* -P <chain> <policy> */
27 static void fwd_r_set_policy(
28 struct iptc_handle
*h
, const char *chain
, const char *policy
30 iptc_set_policy(chain
, policy
, NULL
, h
);
34 static void fwd_r_new_chain(struct iptc_handle
*h
, const char *chain
)
36 iptc_create_chain(chain
, h
);
39 /* -A <chain1> -j <chain2> */
40 static void fwd_r_jump_chain(
41 struct iptc_handle
*h
, const char *chain1
, const char *chain2
43 struct fwd_xt_rule
*r
;
45 if( (r
= fwd_xt_init_rule(h
)) != NULL
)
47 fwd_xt_get_target(r
, chain2
);
48 fwd_xt_exec_rule(r
, chain1
);
52 /* -A <chain> -m state --state INVALID -j DROP */
53 static void fwd_r_drop_invalid(struct iptc_handle
*h
, const char *chain
)
55 struct fwd_xt_rule
*r
;
56 struct xtables_match
*m
;
58 if( (r
= fwd_xt_init_rule(h
)) != NULL
)
60 if( (m
= fwd_xt_get_match(r
, "state")) != NULL
)
62 fwd_xt_parse_match(r
, m
, "--state", "INVALID");
63 fwd_xt_get_target(r
, "DROP");
64 fwd_xt_exec_rule(r
, chain
);
69 /* -A <chain> -m state --state RELATED,ESTABLISHED -j ACCEPT */
70 static void fwd_r_accept_related(struct iptc_handle
*h
, const char *chain
)
72 struct fwd_xt_rule
*r
;
73 struct xtables_match
*m
;
75 if( (r
= fwd_xt_init_rule(h
)) != NULL
)
77 if( (m
= fwd_xt_get_match(r
, "state")) != NULL
)
79 fwd_xt_parse_match(r
, m
, "--state", "RELATED,ESTABLISHED");
80 fwd_xt_get_target(r
, "ACCEPT");
81 fwd_xt_exec_rule(r
, chain
);
86 /* -A INPUT -i lo -j ACCEPT; -A OUTPUT -o lo -j ACCEPT */
87 static void fwd_r_accept_lo(struct iptc_handle
*h
)
89 struct fwd_network_list n
;
90 struct fwd_xt_rule
*r
;
94 if( (r
= fwd_xt_init_rule(h
)) != NULL
)
96 fwd_xt_parse_in(r
, &n
, 0);
97 fwd_xt_get_target(r
, "ACCEPT");
98 fwd_xt_exec_rule(r
, "INPUT");
101 if( (r
= fwd_xt_init_rule(h
)) != NULL
)
103 fwd_xt_parse_out(r
, &n
, 0);
104 fwd_xt_get_target(r
, "ACCEPT");
105 fwd_xt_exec_rule(r
, "OUTPUT");
109 /* build syn_flood chain and jump rule */
110 static void fwd_r_add_synflood(struct iptc_handle
*h
, struct fwd_defaults
*def
)
113 struct fwd_xt_rule
*r
;
114 struct xtables_match
*m
;
118 fwd_r_new_chain(h
, "syn_flood");
121 if( (r
= fwd_xt_init_rule(h
)) != NULL
)
125 fwd_xt_parse_proto(r
, &p
, 0);
128 if( (m
= fwd_xt_get_match(r
, "tcp")) != NULL
)
130 fwd_xt_parse_match(r
, m
, "--syn");
133 /* -m limit --limit x/second --limit-burst y */
134 if( (m
= fwd_xt_get_match(r
, "limit")) != NULL
)
136 sprintf(buf
, "%i/second", def
->syn_rate
);
137 fwd_xt_parse_match(r
, m
, "--limit", buf
);
139 sprintf(buf
, "%i", def
->syn_burst
);
140 fwd_xt_parse_match(r
, m
, "--limit-burst", buf
);
143 /* -j RETURN; -A syn_flood */
144 fwd_xt_get_target(r
, "RETURN");
145 fwd_xt_exec_rule(r
, "syn_flood");
149 if( (r
= fwd_xt_init_rule(h
)) != NULL
)
151 /* -j DROP; -A syn_flood */
152 fwd_xt_get_target(r
, "DROP");
153 fwd_xt_exec_rule(r
, "syn_flood");
156 /* jump to syn_flood rule */
157 if( (r
= fwd_xt_init_rule(h
)) != NULL
)
161 fwd_xt_parse_proto(r
, &p
, 0);
164 if( (m
= fwd_xt_get_match(r
, "tcp")) != NULL
)
166 fwd_xt_parse_match(r
, m
, "--syn");
169 /* -j syn_flood; -A INPUT */
170 fwd_xt_get_target(r
, "syn_flood");
171 fwd_xt_exec_rule(r
, "INPUT");
175 /* build reject target chain */
176 static void fwd_r_handle_reject(struct iptc_handle
*h
)
179 struct fwd_xt_rule
*r
;
180 struct xtables_target
*t
;
182 /* -N handle_reject */
183 fwd_r_new_chain(h
, "handle_reject");
185 /* tcp reject rule */
186 if( (r
= fwd_xt_init_rule(h
)) != NULL
)
190 fwd_xt_parse_proto(r
, &p
, 0);
192 /* -j REJECT --reject-with tcp-reset */
193 if( (t
= fwd_xt_get_target(r
, "REJECT")) != NULL
)
195 fwd_xt_parse_target(r
, t
, "--reject-with", "tcp-reset");
198 /* -A handle_reject */
199 fwd_xt_exec_rule(r
, "handle_reject");
202 /* common reject rule */
203 if( (r
= fwd_xt_init_rule(h
)) != NULL
)
205 /* -j REJECT --reject-with icmp-port-unreachable */
206 if( (t
= fwd_xt_get_target(r
, "REJECT")) != NULL
)
208 fwd_xt_parse_target(r
, t
, "--reject-with",
209 "icmp-port-unreachable");
212 /* -A handle_reject */
213 fwd_xt_exec_rule(r
, "handle_reject");
217 /* build drop target chain */
218 static void fwd_r_handle_drop(struct iptc_handle
*h
)
220 struct fwd_xt_rule
*r
;
223 fwd_r_new_chain(h
, "handle_drop");
225 /* common drop rule */
226 if( (r
= fwd_xt_init_rule(h
)) != NULL
)
228 /* -j DROP; -A handle_reject */
229 fwd_xt_get_target(r
, "DROP");
230 fwd_xt_exec_rule(r
, "handle_reject");
234 /* build accept target chain */
235 static void fwd_r_handle_accept(struct iptc_handle
*h
)
237 struct fwd_xt_rule
*r
;
239 /* -N handle_accept */
240 fwd_r_new_chain(h
, "handle_accept");
242 /* common accept rule */
243 if( (r
= fwd_xt_init_rule(h
)) != NULL
)
245 /* -j ACCEPT; -A handle_accept */
246 fwd_xt_get_target(r
, "ACCEPT");
247 fwd_xt_exec_rule(r
, "handle_accept");
251 /* add comment match */
252 static void fwd_r_add_comment(
253 struct fwd_xt_rule
*r
, const char *t
, struct fwd_zone
*z
,
254 struct fwd_network_list
*n
, struct fwd_network_list
*n2
256 struct xtables_match
*m
;
259 if( (m
= fwd_xt_get_match(r
, "comment")) != NULL
)
261 if( (n
!= NULL
) && (n2
!= NULL
) )
262 snprintf(buf
, sizeof(buf
), "%s:%s src:%s dest:%s",
263 t
, z
->name
, n
->name
, n2
->name
);
264 else if( (n
== NULL
) && (n2
!= NULL
) )
265 snprintf(buf
, sizeof(buf
), "%s:%s dest:%s", t
, z
->name
, n2
->name
);
267 snprintf(buf
, sizeof(buf
), "%s:%s src:%s", t
, z
->name
, n
->name
);
269 fwd_xt_parse_match(r
, m
, "--comment", buf
);
273 /* add --sport (if applicable) */
274 static void fwd_r_add_sport(
275 struct fwd_xt_rule
*r
, struct fwd_portrange
*p
277 int proto
= r
->entry
->ip
.proto
;
279 struct xtables_match
*m
;
281 /* have portrange and proto is tcp or udp ... */
282 if( (p
!= NULL
) && ((proto
== 6) || (proto
== 17)) )
285 if( (m
= fwd_xt_get_match(r
, (proto
== 6) ? "tcp" : "udp")) != NULL
)
287 snprintf(buf
, sizeof(buf
), "%u:%u", p
->min
, p
->max
);
288 fwd_xt_parse_match(r
, m
, "--sport", buf
);
293 /* add --dport (if applicable) */
294 static void fwd_r_add_dport(
295 struct fwd_xt_rule
*r
, struct fwd_portrange
*p
297 int proto
= r
->entry
->ip
.proto
;
299 struct xtables_match
*m
;
301 /* have portrange and proto is tcp or udp ... */
302 if( (p
!= NULL
) && ((proto
== 6) || (proto
== 17)) )
305 if( (m
= fwd_xt_get_match(r
, (proto
== 6) ? "tcp" : "udp")) != NULL
)
307 snprintf(buf
, sizeof(buf
), "%u:%u", p
->min
, p
->max
);
308 fwd_xt_parse_match(r
, m
, "--dport", buf
);
313 /* add --icmp-type (of applicable) */
314 static void fwd_r_add_icmptype(
315 struct fwd_xt_rule
*r
, struct fwd_icmptype
*i
317 int proto
= r
->entry
->ip
.proto
;
318 struct xtables_match
*m
;
321 /* have icmp-type and proto is icmp ... */
322 if( (i
!= NULL
) && (proto
== 1) )
325 if( (m
= fwd_xt_get_match(r
, "icmp")) != NULL
)
328 snprintf(buf
, sizeof(buf
), "%s", i
->name
);
330 snprintf(buf
, sizeof(buf
), "%u/%u", i
->type
, i
->code
);
332 fwd_xt_parse_match(r
, m
, "--icmp-type", buf
);
337 /* add -m mac --mac-source ... */
338 static void fwd_r_add_srcmac(
339 struct fwd_xt_rule
*r
, struct fwd_mac
*mac
341 struct xtables_match
*m
;
346 if( (m
= fwd_xt_get_match(r
, "mac")) != NULL
)
348 snprintf(buf
, sizeof(buf
), "%02x:%02x:%02x:%02x:%02x:%02x",
349 mac
->mac
[0], mac
->mac
[1], mac
->mac
[2],
350 mac
->mac
[3], mac
->mac
[4], mac
->mac
[5]);
352 fwd_xt_parse_match(r
, m
, "--mac-source", buf
);
357 /* add policy target */
358 static void fwd_r_add_policytarget(
359 struct fwd_xt_rule
*r
, enum fwd_policy pol
364 fwd_xt_get_target(r
, "handle_accept");
368 fwd_xt_get_target(r
, "handle_reject");
373 fwd_xt_get_target(r
, "handle_drop");
378 /* add dnat target */
379 static void fwd_r_add_dnattarget(
380 struct fwd_xt_rule
*r
, struct fwd_cidr
*c
, struct fwd_portrange
*p
382 struct xtables_target
*t
;
387 if( (t
= fwd_xt_get_target(r
, "DNAT")) != NULL
)
390 snprintf(buf
, sizeof(buf
), "%s:%u-%u",
391 inet_ntoa(c
->addr
), p
->min
, p
->max
);
393 snprintf(buf
, sizeof(buf
), "%s", inet_ntoa(c
->addr
));
395 fwd_xt_parse_target(r
, t
, "--to-destination", buf
);
400 /* parse comment string and look for match */
401 static int fwd_r_cmp(const char *what
, const char *cmt
, const char *cmp
)
405 printf("CMP: %s %s %s\n", what
, cmt
, cmp
);
407 if( (match
= strstr(cmt
, what
)) == NULL
)
410 match
+= strlen(what
);
412 if( strncmp(match
, cmp
, strlen(cmp
)) != 0 )
415 if( (match
[strlen(cmp
)] != ' ') && (match
[strlen(cmp
)] != '\0') )
422 static void fwd_ipt_defaults_create(struct fwd_data
*d
)
424 struct fwd_defaults
*def
= &d
->section
.defaults
;
425 struct iptc_handle
*h_filter
, *h_nat
;
427 if( !(h_filter
= iptc_init("filter")) || !(h_nat
= iptc_init("nat")) )
428 fwd_fatal("Unable to obtain libiptc handle");
431 fwd_r_set_policy(h_filter
, "INPUT",
432 def
->input
== FWD_P_ACCEPT
? "ACCEPT" : "DROP");
433 fwd_r_set_policy(h_filter
, "OUTPUT",
434 def
->output
== FWD_P_ACCEPT
? "ACCEPT" : "DROP");
435 fwd_r_set_policy(h_filter
, "FORWARD",
436 def
->forward
== FWD_P_ACCEPT
? "ACCEPT" : "DROP");
438 /* invalid state drop */
439 if( def
->drop_invalid
)
441 fwd_r_drop_invalid(h_filter
, "INPUT");
442 fwd_r_drop_invalid(h_filter
, "OUTPUT");
443 fwd_r_drop_invalid(h_filter
, "FORWARD");
446 /* default accept related */
447 fwd_r_accept_related(h_filter
, "INPUT");
448 fwd_r_accept_related(h_filter
, "OUTPUT");
449 fwd_r_accept_related(h_filter
, "FORWARD");
451 /* default accept on lo */
452 fwd_r_accept_lo(h_filter
);
454 /* syn flood protection */
457 fwd_r_add_synflood(h_filter
, def
);
460 /* rule container chains */
461 fwd_r_new_chain(h_filter
, "mssfix");
462 fwd_r_new_chain(h_filter
, "zones");
463 fwd_r_new_chain(h_filter
, "rules");
464 fwd_r_new_chain(h_filter
, "redirects");
465 fwd_r_new_chain(h_filter
, "forwardings");
466 fwd_r_jump_chain(h_filter
, "INPUT", "rules");
467 fwd_r_jump_chain(h_filter
, "FORWARD", "mssfix");
468 fwd_r_jump_chain(h_filter
, "FORWARD", "zones");
469 fwd_r_jump_chain(h_filter
, "FORWARD", "rules");
470 fwd_r_jump_chain(h_filter
, "FORWARD", "redirects");
471 fwd_r_jump_chain(h_filter
, "FORWARD", "forwardings");
472 fwd_r_new_chain(h_nat
, "zonemasq");
473 fwd_r_new_chain(h_nat
, "redirects");
474 fwd_r_new_chain(h_nat
, "loopback");
475 fwd_r_jump_chain(h_nat
, "POSTROUTING", "zonemasq");
476 fwd_r_jump_chain(h_nat
, "PREROUTING", "redirects");
477 fwd_r_jump_chain(h_nat
, "POSTROUTING", "loopback");
479 /* standard drop, accept, reject chain */
480 fwd_r_handle_drop(h_filter
);
481 fwd_r_handle_accept(h_filter
);
482 fwd_r_handle_reject(h_filter
);
485 if( !iptc_commit(h_nat
) )
486 fwd_fatal("Cannot commit nat table: %s", iptc_strerror(errno
));
488 if( !iptc_commit(h_filter
) )
489 fwd_fatal("Cannot commit filter table: %s", iptc_strerror(errno
));
496 void fwd_ipt_build_ruleset(struct fwd_handle
*h
)
502 for( e
= h
->conf
; e
; e
= e
->next
)
507 printf("\n## DEFAULTS\n");
508 fwd_ipt_defaults_create(e
);
512 printf("\n## INCLUDE %s\n", e
->section
.include
.path
);
526 static struct fwd_zone
*
527 fwd_lookup_zone(struct fwd_handle
*h
, const char *net
)
530 struct fwd_network_list
*n
;
532 for( e
= h
->conf
; e
; e
= e
->next
)
533 if( e
->type
== FWD_S_ZONE
)
534 for( n
= e
->section
.zone
.networks
; n
; n
= n
->next
)
535 if( !strcmp(n
->name
, net
) )
536 return &e
->section
.zone
;
541 static struct fwd_network_list
*
542 fwd_lookup_network(struct fwd_zone
*z
, const char *net
)
544 struct fwd_network_list
*n
;
546 for( n
= z
->networks
; n
; n
= n
->next
)
547 if( !strcmp(n
->name
, net
) )
553 static struct fwd_addr_list
*
554 fwd_lookup_addr(struct fwd_handle
*h
, struct fwd_network_list
*n
)
556 struct fwd_addr_list
*a
;
559 for( a
= h
->addrs
; a
; a
= a
->next
)
560 if( !strcmp(a
->ifname
, n
->ifname
) )
566 void fwd_ipt_addif(struct fwd_handle
*h
, const char *net
)
571 struct fwd_redirect
*r
;
572 struct fwd_forwarding
*f
;
573 struct fwd_addr_list
*a
, *a2
;
574 struct fwd_network_list
*n
, *n2
;
577 struct fwd_xt_rule
*x
;
578 struct xtables_match
*m
;
579 struct xtables_target
*t
;
581 struct iptc_handle
*h_filter
, *h_nat
;
583 if( !(h_filter
= iptc_init("filter")) || !(h_nat
= iptc_init("nat")) )
584 fwd_fatal("Unable to obtain libiptc handle");
587 if( !(z
= fwd_lookup_zone(h
, net
)) )
590 if( !(n
= fwd_lookup_network(z
, net
)) )
593 if( !(a
= fwd_lookup_addr(h
, n
)) )
596 printf("\n\n#\n# addif(%s)\n#\n", net
);
598 /* Build masquerading rule */
601 printf("\n# Net %s (%s) - masq\n", n
->name
, n
->ifname
);
603 if( (x
= fwd_xt_init_rule(h_nat
)) != NULL
)
605 fwd_xt_parse_out(x
, n
, 0); /* -o ... */
606 fwd_xt_get_target(x
, "MASQUERADE"); /* -j MASQUERADE */
607 fwd_r_add_comment(x
, "masq", z
, NULL
, n
); /* -m comment ... */
608 fwd_xt_exec_rule(x
, "zonemasq"); /* -A zonemasq */
612 /* Build MSS fix rule */
615 printf("\n# Net %s (%s) - mtu_fix\n", n
->name
, n
->ifname
);
617 if( (x
= fwd_xt_init_rule(h_filter
)) != NULL
)
620 fwd_xt_parse_out(x
, n
, 0); /* -o ... */
621 fwd_xt_parse_proto(x
, &p
, 0); /* -p tcp */
623 /* -m tcp --tcp-flags SYN,RST SYN */
624 if( (m
= fwd_xt_get_match(x
, "tcp")) != NULL
)
625 fwd_xt_parse_match(x
, m
, "--tcp-flags", "SYN,RST", "SYN");
627 /* -j TCPMSS --clamp-mss-to-pmtu */
628 if( (t
= fwd_xt_get_target(x
, "TCPMSS")) != NULL
)
629 fwd_xt_parse_target(x
, t
, "--clamp-mss-to-pmtu");
632 fwd_r_add_comment(x
, "mssfix", z
, NULL
, n
);
635 fwd_xt_exec_rule(x
, "mssfix");
639 /* Build intra-zone forwarding rules */
640 for( n2
= z
->networks
; n2
; n2
= n2
->next
)
642 if( (a2
= fwd_lookup_addr(h
, n2
)) != NULL
)
644 printf("\n# Net %s (%s) - intra-zone-forwarding"
645 " Z:%s N:%s I:%s -> Z:%s N:%s I:%s\n",
646 n
->name
, n
->ifname
, z
->name
, n
->name
, n
->ifname
,
647 z
->name
, n2
->name
, n2
->ifname
);
649 if( (x
= fwd_xt_init_rule(h_filter
)) != NULL
)
651 fwd_xt_parse_in(x
, n
, 0); /* -i ... */
652 fwd_xt_parse_out(x
, n2
, 0); /* -o ... */
653 fwd_r_add_policytarget(x
, z
->forward
); /* -j handle_... */
654 fwd_r_add_comment(x
, "zone", z
, n
, n2
); /* -m comment ... */
655 fwd_xt_exec_rule(x
, "zones"); /* -A zones */
660 /* Build inter-zone forwarding rules */
661 for( e
= z
->forwardings
; e
&& (f
= &e
->section
.forwarding
); e
= e
->next
)
663 for( n2
= f
->dest
->networks
; n2
; n2
= n2
->next
)
665 printf("\n# Net %s (%s) - inter-zone-forwarding"
666 " Z:%s N:%s I:%s -> Z:%s N:%s I:%s\n",
667 n
->name
, n
->ifname
, z
->name
, n
->name
, n
->ifname
,
668 f
->dest
->name
, n2
->name
, n2
->ifname
);
670 /* Build forwarding rule */
671 if( (x
= fwd_xt_init_rule(h_filter
)) != NULL
)
673 fwd_xt_parse_in(x
, n
, 0); /* -i ... */
674 fwd_xt_parse_out(x
, n2
, 0); /* -o ... */
675 fwd_r_add_policytarget(x
, FWD_P_ACCEPT
); /* -j handle_... */
676 fwd_r_add_comment(x
, "forward", z
, n
, n2
); /* -m comment ... */
677 fwd_xt_exec_rule(x
, "forwardings"); /* -A forwardings */
682 /* Build DNAT rules */
683 for( e
= z
->redirects
; e
&& (r
= &e
->section
.redirect
); e
= e
->next
)
685 printf("\n# Net %s (%s) - redirect Z:%s N:%s I:%s\n",
686 n
->name
, n
->ifname
, z
->name
, n
->name
, n
->ifname
);
689 if( (x
= fwd_xt_init_rule(h_nat
)) != NULL
)
691 fwd_xt_parse_in(x
, n
, 0); /* -i ... */
692 fwd_xt_parse_src(x
, r
->src_ip
, 0); /* -s ... */
693 fwd_xt_parse_dest(x
, &a
->ipaddr
, 0); /* -d ... */
694 fwd_xt_parse_proto(x
, r
->proto
, 0); /* -p ... */
695 fwd_r_add_sport(x
, r
->src_port
); /* --sport ... */
696 fwd_r_add_dport(x
, r
->src_dport
); /* --dport ... */
697 fwd_r_add_srcmac(x
, r
->src_mac
); /* -m mac --mac-source ... */
698 fwd_r_add_dnattarget(x
, r
->dest_ip
, r
->dest_port
); /* -j DNAT ... */
699 fwd_r_add_comment(x
, "redir", z
, n
, NULL
); /* -m comment ... */
700 fwd_xt_exec_rule(x
, "redirects"); /* -A redirects */
704 if( (x
= fwd_xt_init_rule(h_filter
)) != NULL
)
706 fwd_xt_parse_in(x
, n
, 0); /* -i ... */
707 fwd_xt_parse_src(x
, r
->src_ip
, 0); /* -s ... */
708 fwd_xt_parse_dest(x
, r
->dest_ip
, 0); /* -d ... */
709 fwd_xt_parse_proto(x
, r
->proto
, 0); /* -p ... */
710 fwd_r_add_srcmac(x
, r
->src_mac
); /* -m mac --mac-source ... */
711 fwd_r_add_sport(x
, r
->src_port
); /* --sport ... */
712 fwd_r_add_dport(x
, r
->dest_port
); /* --dport ... */
713 fwd_r_add_policytarget(x
, FWD_P_ACCEPT
); /* -j handle_accept */
714 fwd_r_add_comment(x
, "redir", z
, n
, NULL
); /* -m comment ... */
715 fwd_xt_exec_rule(x
, "redirects"); /* -A redirects */
718 /* Add loopback rule if neither src_ip nor src_mac are defined */
719 if( !r
->src_ip
&& !r
->src_mac
)
721 if( (x
= fwd_xt_init_rule(h_nat
)) != NULL
)
723 fwd_xt_parse_in(x
, n
, 1); /* -i ! ... */
724 fwd_xt_parse_dest(x
, r
->dest_ip
, 0); /* -d ... */
725 fwd_xt_parse_proto(x
, r
->proto
, 0); /* -p ... */
726 fwd_r_add_sport(x
, r
->src_port
); /* --sport ... */
727 fwd_r_add_dport(x
, r
->src_dport
); /* --dport ... */
728 fwd_xt_get_target(x
, "MASQUERADE"); /* -j MASQUERADE */
729 fwd_r_add_comment(x
, "redir", z
, n
, NULL
); /* -m comment ... */
730 fwd_xt_exec_rule(x
, "loopback"); /* -A loopback */
736 for( e
= z
->rules
; e
&& (c
= &e
->section
.rule
); e
= e
->next
)
738 /* Has destination, add forward rule for each network in target zone */
741 for( n2
= c
->dest
->networks
; n2
; n2
= n2
->next
)
743 printf("\n# Net %s (%s) - rule+dest"
744 " Z:%s N:%s I:%s -> Z:%s N:%s I:%s\n",
745 n
->name
, n
->ifname
, z
->name
, n
->name
, n
->ifname
,
746 f
->dest
->name
, n2
->name
, n2
->ifname
);
748 if( (x
= fwd_xt_init_rule(h_filter
)) != NULL
)
750 fwd_xt_parse_in(x
, n
, 0); /* -i ... */
751 fwd_xt_parse_out(x
, n2
, 0); /* -o ... */
752 fwd_xt_parse_src(x
, c
->src_ip
, 0); /* -s ... */
753 fwd_xt_parse_dest(x
, c
->dest_ip
, 0); /* -d ... */
754 fwd_xt_parse_proto(x
, c
->proto
, 0); /* -p ... */
755 fwd_r_add_icmptype(x
, c
->icmp_type
); /* --icmp-type ... */
756 fwd_r_add_srcmac(x
, c
->src_mac
); /* --mac-source ... */
757 fwd_r_add_sport(x
, c
->src_port
); /* --sport ... */
758 fwd_r_add_dport(x
, c
->dest_port
); /* --dport ... */
759 fwd_r_add_policytarget(x
, c
->target
); /* -j handle_... */
760 fwd_r_add_comment(x
, "rule", z
, n
, n2
); /* -m comment ... */
761 fwd_xt_exec_rule(x
, "rules"); /* -A rules */
766 /* No destination specified, treat it as input rule */
769 printf("\n# Net %s (%s) - rule Z:%s N:%s I:%s\n",
770 n
->name
, n
->ifname
, z
->name
, n
->name
, n
->ifname
);
772 if( (x
= fwd_xt_init_rule(h_filter
)) != NULL
)
774 fwd_xt_parse_in(x
, n
, 0); /* -i ... */
775 fwd_xt_parse_src(x
, c
->src_ip
, 0); /* -s ... */
776 fwd_xt_parse_dest(x
, c
->dest_ip
, 0); /* -d ... */
777 fwd_xt_parse_proto(x
, c
->proto
, 0); /* -p ... */
778 fwd_r_add_icmptype(x
, c
->icmp_type
); /* --icmp-type ... */
779 fwd_r_add_srcmac(x
, c
->src_mac
); /* --mac-source ... */
780 fwd_r_add_sport(x
, c
->src_port
); /* --sport ... */
781 fwd_r_add_dport(x
, c
->dest_port
); /* --dport ... */
782 fwd_r_add_policytarget(x
, c
->target
); /* -j handle_... */
783 fwd_r_add_comment(x
, "rule", z
, n
, NULL
); /* -m comment ... */
784 fwd_xt_exec_rule(x
, "rules"); /* -A rules */
789 if( !iptc_commit(h_nat
) )
790 fwd_fatal("Cannot commit nat table: %s", iptc_strerror(errno
));
792 if( !iptc_commit(h_filter
) )
793 fwd_fatal("Cannot commit filter table: %s", iptc_strerror(errno
));
800 static void fwd_ipt_delif_table(struct iptc_handle
*h
, const char *net
)
802 struct xt_entry_match
*m
;
804 const char *chain
, *comment
;
805 size_t off
= 0, num
= 0;
808 for( chain
= iptc_first_chain(h
); chain
;
809 chain
= iptc_next_chain(h
)
812 for( e
= iptc_first_rule(chain
, h
), num
= 0; e
;
813 e
= iptc_next_rule(e
, h
), num
++
817 /* skip entries w/o matches */
818 if( ! e
->target_offset
)
821 /* iterate matches */
822 for( off
= sizeof(struct ipt_entry
);
823 off
< e
->target_offset
;
824 off
+= m
->u
.match_size
829 if( ! strcmp(m
->u
.user
.name
, "comment") )
831 /* better use struct_xt_comment_info but well... */
832 comment
= (void *)m
+ sizeof(struct xt_entry_match
);
834 if( fwd_r_cmp("src:", comment
, net
) )
836 e
= iptc_next_rule(e
, h
);
837 iptc_delete_num_entry(chain
, num
, h
);
850 void fwd_ipt_delif(struct fwd_handle
*h
, const char *net
)
852 struct iptc_handle
*h_filter
, *h_nat
;
854 if( !(h_filter
= iptc_init("filter")) || !(h_nat
= iptc_init("nat")) )
855 fwd_fatal("Unable to obtain libiptc handle");
858 printf("\n\n#\n# delif(%s)\n#\n", net
);
860 /* delete network related rules */
861 fwd_ipt_delif_table(h_nat
, net
);
862 fwd_ipt_delif_table(h_filter
, net
);
865 if( !iptc_commit(h_nat
) )
866 fwd_fatal("Cannot commit nat table: %s", iptc_strerror(errno
));
868 if( !iptc_commit(h_filter
) )
869 fwd_fatal("Cannot commit filter table: %s", iptc_strerror(errno
));
876 static void fwd_ipt_clear_ruleset_table(struct iptc_handle
*h
)
880 /* pass 1: flush all chains */
881 for( chain
= iptc_first_chain(h
); chain
;
882 chain
= iptc_next_chain(h
)
884 iptc_flush_entries(chain
, h
);
887 /* pass 2: remove user defined chains */
888 for( chain
= iptc_first_chain(h
); chain
;
889 chain
= iptc_next_chain(h
)
891 if( ! iptc_builtin(chain
, h
) )
892 iptc_delete_chain(chain
, h
);
896 void fwd_ipt_clear_ruleset(struct fwd_handle
*h
)
898 struct iptc_handle
*h_filter
, *h_nat
;
900 if( !(h_filter
= iptc_init("filter")) || !(h_nat
= iptc_init("nat")) )
901 fwd_fatal("Unable to obtain libiptc handle");
904 fwd_ipt_clear_ruleset_table(h_nat
);
905 fwd_ipt_clear_ruleset_table(h_filter
);
907 /* revert policies */
908 fwd_r_set_policy(h_filter
, "INPUT", "ACCEPT");
909 fwd_r_set_policy(h_filter
, "OUTPUT", "ACCEPT");
910 fwd_r_set_policy(h_filter
, "FORWARD", "ACCEPT");
913 if( !iptc_commit(h_nat
) )
914 fwd_fatal("Cannot commit nat table: %s", iptc_strerror(errno
));
916 if( !iptc_commit(h_filter
) )
917 fwd_fatal("Cannot commit filter table: %s", iptc_strerror(errno
));