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"
24 #include "fwd_utils.h"
27 /* -P <chain> <policy> */
28 static void fwd_r_set_policy(
29 struct iptc_handle *h, const char *chain, const char *policy
31 iptc_set_policy(chain, policy, NULL, h);
35 static void fwd_r_new_chain(struct iptc_handle *h, const char *chain)
37 iptc_create_chain(chain, h);
40 /* -A <chain1> -j <chain2> */
41 static void fwd_r_jump_chain(
42 struct iptc_handle *h, const char *chain1, const char *chain2
44 struct fwd_xt_rule *r;
46 if( (r = fwd_xt_init_rule(h)) != NULL )
48 fwd_xt_get_target(r, chain2);
49 fwd_xt_append_rule(r, chain1);
53 /* -A <chain> -m state --state INVALID -j DROP */
54 static void fwd_r_drop_invalid(struct iptc_handle *h, const char *chain)
56 struct fwd_xt_rule *r;
57 struct xtables_match *m;
59 if( (r = fwd_xt_init_rule(h)) != NULL )
61 if( (m = fwd_xt_get_match(r, "state")) != NULL )
63 fwd_xt_parse_match(r, m, "--state", "INVALID");
64 fwd_xt_get_target(r, "DROP");
65 fwd_xt_append_rule(r, chain);
70 /* -A <chain> -m state --state RELATED,ESTABLISHED -j ACCEPT */
71 static void fwd_r_accept_related(struct iptc_handle *h, const char *chain)
73 struct fwd_xt_rule *r;
74 struct xtables_match *m;
76 if( (r = fwd_xt_init_rule(h)) != NULL )
78 if( (m = fwd_xt_get_match(r, "state")) != NULL )
80 fwd_xt_parse_match(r, m, "--state", "RELATED,ESTABLISHED");
81 fwd_xt_get_target(r, "ACCEPT");
82 fwd_xt_append_rule(r, chain);
87 /* -A INPUT -i lo -j ACCEPT; -A OUTPUT -o lo -j ACCEPT */
88 static void fwd_r_accept_lo(struct iptc_handle *h)
91 struct fwd_xt_rule *r;
95 if( (r = fwd_xt_init_rule(h)) != NULL )
97 fwd_xt_parse_in(r, &n, 0);
98 fwd_xt_get_target(r, "ACCEPT");
99 fwd_xt_append_rule(r, "INPUT");
102 if( (r = fwd_xt_init_rule(h)) != NULL )
104 fwd_xt_parse_out(r, &n, 0);
105 fwd_xt_get_target(r, "ACCEPT");
106 fwd_xt_append_rule(r, "OUTPUT");
110 /* build syn_flood chain and jump rule */
111 static void fwd_r_add_synflood(struct iptc_handle *h, struct fwd_defaults *def)
114 struct fwd_xt_rule *r;
115 struct xtables_match *m;
119 fwd_r_new_chain(h, "syn_flood");
122 if( (r = fwd_xt_init_rule(h)) != NULL )
126 fwd_xt_parse_proto(r, &p, 0);
129 if( (m = fwd_xt_get_match(r, "tcp")) != NULL )
131 fwd_xt_parse_match(r, m, "--syn");
134 /* -m limit --limit x/second --limit-burst y */
135 if( (m = fwd_xt_get_match(r, "limit")) != NULL )
137 sprintf(buf, "%i/second", def->syn_rate);
138 fwd_xt_parse_match(r, m, "--limit", buf);
140 sprintf(buf, "%i", def->syn_burst);
141 fwd_xt_parse_match(r, m, "--limit-burst", buf);
144 /* -j RETURN; -A syn_flood */
145 fwd_xt_get_target(r, "RETURN");
146 fwd_xt_append_rule(r, "syn_flood");
150 if( (r = fwd_xt_init_rule(h)) != NULL )
152 /* -j DROP; -A syn_flood */
153 fwd_xt_get_target(r, "DROP");
154 fwd_xt_append_rule(r, "syn_flood");
157 /* jump to syn_flood rule */
158 if( (r = fwd_xt_init_rule(h)) != NULL )
162 fwd_xt_parse_proto(r, &p, 0);
165 if( (m = fwd_xt_get_match(r, "tcp")) != NULL )
167 fwd_xt_parse_match(r, m, "--syn");
170 /* -j syn_flood; -A INPUT */
171 fwd_xt_get_target(r, "syn_flood");
172 fwd_xt_append_rule(r, "INPUT");
176 /* build reject target chain */
177 static void fwd_r_handle_reject(struct iptc_handle *h)
180 struct fwd_xt_rule *r;
181 struct xtables_target *t;
183 /* -N handle_reject */
184 fwd_r_new_chain(h, "handle_reject");
186 /* tcp reject rule */
187 if( (r = fwd_xt_init_rule(h)) != NULL )
191 fwd_xt_parse_proto(r, &p, 0);
193 /* -j REJECT --reject-with tcp-reset */
194 if( (t = fwd_xt_get_target(r, "REJECT")) != NULL )
196 fwd_xt_parse_target(r, t, "--reject-with", "tcp-reset");
199 /* -A handle_reject */
200 fwd_xt_append_rule(r, "handle_reject");
203 /* common reject rule */
204 if( (r = fwd_xt_init_rule(h)) != NULL )
206 /* -j REJECT --reject-with icmp-port-unreachable */
207 if( (t = fwd_xt_get_target(r, "REJECT")) != NULL )
209 fwd_xt_parse_target(r, t, "--reject-with",
210 "icmp-port-unreachable");
213 /* -A handle_reject */
214 fwd_xt_append_rule(r, "handle_reject");
218 /* build drop target chain */
219 static void fwd_r_handle_drop(struct iptc_handle *h)
221 struct fwd_xt_rule *r;
224 fwd_r_new_chain(h, "handle_drop");
226 /* common drop rule */
227 if( (r = fwd_xt_init_rule(h)) != NULL )
229 /* -j DROP; -A handle_drop */
230 fwd_xt_get_target(r, "DROP");
231 fwd_xt_append_rule(r, "handle_drop");
235 /* build accept target chain */
236 static void fwd_r_handle_accept(struct iptc_handle *h)
238 struct fwd_xt_rule *r;
240 /* -N handle_accept */
241 fwd_r_new_chain(h, "handle_accept");
243 /* common accept rule */
244 if( (r = fwd_xt_init_rule(h)) != NULL )
246 /* -j ACCEPT; -A handle_accept */
247 fwd_xt_get_target(r, "ACCEPT");
248 fwd_xt_append_rule(r, "handle_accept");
252 /* add comment match */
253 static void fwd_r_add_comment(
254 struct fwd_xt_rule *r, const char *t, struct fwd_zone *z,
255 struct fwd_network *n
257 struct xtables_match *m;
260 if( (m = fwd_xt_get_match(r, "comment")) != NULL )
262 snprintf(buf, sizeof(buf), "%s:net=%s zone=%s", t, n->name, z->name);
263 fwd_xt_parse_match(r, m, "--comment", buf);
267 /* add --sport (if applicable) */
268 static void fwd_r_add_sport(
269 struct fwd_xt_rule *r, struct fwd_portrange *p
271 int proto = r->entry->ip.proto;
273 struct xtables_match *m;
275 /* have portrange and proto is tcp or udp ... */
276 if( (p != NULL) && ((proto == 6) || (proto == 17)) )
279 if( (m = fwd_xt_get_match(r, (proto == 6) ? "tcp" : "udp")) != NULL )
281 snprintf(buf, sizeof(buf), "%u:%u", p->min, p->max);
282 fwd_xt_parse_match(r, m, "--sport", buf);
287 /* add --dport (if applicable) */
288 static void fwd_r_add_dport(
289 struct fwd_xt_rule *r, struct fwd_portrange *p
291 int proto = r->entry->ip.proto;
293 struct xtables_match *m;
295 /* have portrange and proto is tcp or udp ... */
296 if( (p != NULL) && ((proto == 6) || (proto == 17)) )
299 if( (m = fwd_xt_get_match(r, (proto == 6) ? "tcp" : "udp")) != NULL )
301 snprintf(buf, sizeof(buf), "%u:%u", p->min, p->max);
302 fwd_xt_parse_match(r, m, "--dport", buf);
307 /* add --icmp-type (of applicable) */
308 static void fwd_r_add_icmptype(
309 struct fwd_xt_rule *r, struct fwd_icmptype *i
311 int proto = r->entry->ip.proto;
312 struct xtables_match *m;
315 /* have icmp-type and proto is icmp ... */
316 if( (i != NULL) && (proto == 1) )
319 if( (m = fwd_xt_get_match(r, "icmp")) != NULL )
322 snprintf(buf, sizeof(buf), "%s", i->name);
324 snprintf(buf, sizeof(buf), "%u/%u", i->type, i->code);
326 fwd_xt_parse_match(r, m, "--icmp-type", buf);
331 /* add -m mac --mac-source ... */
332 static void fwd_r_add_srcmac(
333 struct fwd_xt_rule *r, struct fwd_mac *mac
335 struct xtables_match *m;
340 if( (m = fwd_xt_get_match(r, "mac")) != NULL )
342 snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x",
343 mac->mac[0], mac->mac[1], mac->mac[2],
344 mac->mac[3], mac->mac[4], mac->mac[5]);
346 fwd_xt_parse_match(r, m, "--mac-source", buf);
351 /* add policy target */
352 static void fwd_r_add_policytarget(
353 struct fwd_xt_rule *r, enum fwd_policy pol
358 fwd_xt_get_target(r, "handle_accept");
362 fwd_xt_get_target(r, "handle_reject");
367 fwd_xt_get_target(r, "handle_drop");
372 /* add dnat target */
373 static void fwd_r_add_dnattarget(
374 struct fwd_xt_rule *r, struct fwd_cidr *c, struct fwd_portrange *p
376 struct xtables_target *t;
381 if( (t = fwd_xt_get_target(r, "DNAT")) != NULL )
384 snprintf(buf, sizeof(buf), "%s:%u-%u",
385 inet_ntoa(c->addr), p->min, p->max);
387 snprintf(buf, sizeof(buf), "%s", inet_ntoa(c->addr));
389 fwd_xt_parse_target(r, t, "--to-destination", buf);
394 /* parse comment string and look for match */
395 static int fwd_r_cmp(const char *what, const char *cmt, const char *cmp)
399 if( (match = strstr(cmt, what)) == NULL )
402 match += strlen(what);
404 if( strncmp(match, cmp, strlen(cmp)) != 0 )
407 if( (match[strlen(cmp)] != ' ') && (match[strlen(cmp)] != '\0') )
414 static void fwd_ipt_defaults_create(struct fwd_data *d)
416 struct fwd_defaults *def = &d->section.defaults;
417 struct iptc_handle *h_filter, *h_nat;
419 if( !(h_filter = iptc_init("filter")) || !(h_nat = iptc_init("nat")) )
420 fwd_fatal("Unable to obtain libiptc handle");
423 fwd_r_set_policy(h_filter, "INPUT",
424 def->input == FWD_P_ACCEPT ? "ACCEPT" : "DROP");
425 fwd_r_set_policy(h_filter, "OUTPUT",
426 def->output == FWD_P_ACCEPT ? "ACCEPT" : "DROP");
427 fwd_r_set_policy(h_filter, "FORWARD",
428 def->forward == FWD_P_ACCEPT ? "ACCEPT" : "DROP");
430 /* invalid state drop */
431 if( def->drop_invalid )
433 fwd_r_drop_invalid(h_filter, "INPUT");
434 fwd_r_drop_invalid(h_filter, "OUTPUT");
435 fwd_r_drop_invalid(h_filter, "FORWARD");
438 /* default accept related */
439 fwd_r_accept_related(h_filter, "INPUT");
440 fwd_r_accept_related(h_filter, "OUTPUT");
441 fwd_r_accept_related(h_filter, "FORWARD");
443 /* default accept on lo */
444 fwd_r_accept_lo(h_filter);
446 /* syn flood protection */
449 fwd_r_add_synflood(h_filter, def);
452 /* rule container chains */
453 fwd_r_new_chain(h_filter, "mssfix");
454 fwd_r_new_chain(h_filter, "zones");
455 fwd_r_new_chain(h_filter, "rules");
456 fwd_r_new_chain(h_filter, "redirects");
457 fwd_r_new_chain(h_filter, "forwardings");
458 fwd_r_jump_chain(h_filter, "INPUT", "rules");
459 fwd_r_jump_chain(h_filter, "FORWARD", "mssfix");
460 fwd_r_jump_chain(h_filter, "FORWARD", "zones");
461 fwd_r_jump_chain(h_filter, "FORWARD", "rules");
462 fwd_r_jump_chain(h_filter, "FORWARD", "redirects");
463 fwd_r_jump_chain(h_filter, "FORWARD", "forwardings");
464 fwd_r_new_chain(h_nat, "zonemasq");
465 fwd_r_new_chain(h_nat, "redirects");
466 fwd_r_new_chain(h_nat, "loopback");
467 fwd_r_jump_chain(h_nat, "POSTROUTING", "zonemasq");
468 fwd_r_jump_chain(h_nat, "PREROUTING", "redirects");
469 fwd_r_jump_chain(h_nat, "POSTROUTING", "loopback");
471 /* standard drop, accept, reject chain */
472 fwd_r_handle_drop(h_filter);
473 fwd_r_handle_accept(h_filter);
474 fwd_r_handle_reject(h_filter);
477 if( !iptc_commit(h_nat) )
478 fwd_fatal("Cannot commit nat table: %s", iptc_strerror(errno));
480 if( !iptc_commit(h_filter) )
481 fwd_fatal("Cannot commit filter table: %s", iptc_strerror(errno));
488 void fwd_ipt_build_ruleset(struct fwd_handle *h)
494 for( e = h->conf; e; e = e->next )
499 printf("\n## DEFAULTS\n");
500 fwd_ipt_defaults_create(e);
504 printf("\n## INCLUDE %s\n", e->section.include.path);
518 static struct fwd_zone *
519 fwd_lookup_zone(struct fwd_handle *h, const char *net)
522 struct fwd_network *n;
524 for( e = h->conf; e; e = e->next )
525 if( e->type == FWD_S_ZONE )
526 for( n = e->section.zone.networks; n; n = n->next )
527 if( !strcmp(n->name, net) )
528 return &e->section.zone;
533 static struct fwd_network *
534 fwd_lookup_network(struct fwd_zone *z, const char *net)
536 struct fwd_network *n;
538 for( n = z->networks; n; n = n->next )
539 if( !strcmp(n->name, net) )
545 void fwd_ipt_addif(struct fwd_handle *h, const char *net)
550 struct fwd_redirect *r;
551 struct fwd_forwarding *f;
552 struct fwd_cidr *a, *a2;
553 struct fwd_network *n, *n2;
556 struct fwd_xt_rule *x;
557 struct xtables_match *m;
558 struct xtables_target *t;
560 struct iptc_handle *h_filter, *h_nat;
562 if( !(h_filter = iptc_init("filter")) || !(h_nat = iptc_init("nat")) )
563 fwd_fatal("Unable to obtain libiptc handle");
566 if( !(z = fwd_lookup_zone(h, net)) )
569 if( !(n = fwd_lookup_network(z, net)) )
572 if( !(a = n->addr) || fwd_empty_cidr(a) )
576 printf("\n\n#\n# addif(%s)\n#\n", net);
578 /* Build masquerading rule */
581 printf("\n# Net %s (%s) - masq\n", n->name, n->ifname);
583 if( (x = fwd_xt_init_rule(h_nat)) != NULL )
585 fwd_xt_parse_out(x, n, 0); /* -o ... */
586 fwd_xt_get_target(x, "MASQUERADE"); /* -j MASQUERADE */
587 fwd_r_add_comment(x, "masq", z, n); /* -m comment ... */
588 fwd_xt_append_rule(x, "zonemasq"); /* -A zonemasq */
592 /* Build MSS fix rule */
595 printf("\n# Net %s (%s) - mtu_fix\n", n->name, n->ifname);
597 if( (x = fwd_xt_init_rule(h_filter)) != NULL )
600 fwd_xt_parse_out(x, n, 0); /* -o ... */
601 fwd_xt_parse_proto(x, &p, 0); /* -p tcp */
603 /* -m tcp --tcp-flags SYN,RST SYN */
604 if( (m = fwd_xt_get_match(x, "tcp")) != NULL )
605 fwd_xt_parse_match(x, m, "--tcp-flags", "SYN,RST", "SYN");
607 /* -j TCPMSS --clamp-mss-to-pmtu */
608 if( (t = fwd_xt_get_target(x, "TCPMSS")) != NULL )
609 fwd_xt_parse_target(x, t, "--clamp-mss-to-pmtu");
612 fwd_r_add_comment(x, "mssfix", z, n);
615 fwd_xt_append_rule(x, "mssfix");
619 /* Build intra-zone forwarding rules */
620 for( n2 = z->networks; n2; n2 = n2->next )
622 if( (a2 = n2->addr) != NULL )
624 printf("\n# Net %s (%s) - intra-zone-forwarding"
625 " Z:%s N:%s I:%s -> Z:%s N:%s I:%s\n",
626 n->name, n->ifname, z->name, n->name, n->ifname,
627 z->name, n2->name, n2->ifname);
629 if( (x = fwd_xt_init_rule(h_filter)) != NULL )
631 fwd_xt_parse_in(x, n, 0); /* -i ... */
632 fwd_xt_parse_out(x, n2, 0); /* -o ... */
633 fwd_r_add_policytarget(x, z->forward); /* -j handle_... */
634 fwd_r_add_comment(x, "zone", z, n); /* -m comment ... */
635 fwd_xt_append_rule(x, "zones"); /* -A zones */
640 /* Build inter-zone forwarding rules */
641 for( e = z->forwardings; e && (f = &e->section.forwarding); e = e->next )
643 for( n2 = f->dest->networks; n2; n2 = n2->next )
645 printf("\n# Net %s (%s) - inter-zone-forwarding"
646 " Z:%s N:%s I:%s -> Z:%s N:%s I:%s\n",
647 n->name, n->ifname, z->name, n->name, n->ifname,
648 f->dest->name, n2->name, n2->ifname);
650 /* Build forwarding rule */
651 if( (x = fwd_xt_init_rule(h_filter)) != NULL )
653 fwd_xt_parse_in(x, n, 0); /* -i ... */
654 fwd_xt_parse_out(x, n2, 0); /* -o ... */
655 fwd_r_add_policytarget(x, FWD_P_ACCEPT); /* -j handle_... */
656 fwd_r_add_comment(x, "forward", z, n); /* -m comment ... */
657 fwd_xt_append_rule(x, "forwardings"); /* -A forwardings */
662 /* Build DNAT rules */
663 for( e = z->redirects; e && (r = &e->section.redirect); e = e->next )
665 printf("\n# Net %s (%s) - redirect Z:%s N:%s I:%s\n",
666 n->name, n->ifname, z->name, n->name, n->ifname);
669 if( (x = fwd_xt_init_rule(h_nat)) != NULL )
671 fwd_xt_parse_in(x, n, 0); /* -i ... */
672 fwd_xt_parse_src(x, r->src_ip, 0); /* -s ... */
673 fwd_xt_parse_dest(x, a, 0); /* -d ... */
674 fwd_xt_parse_proto(x, r->proto, 0); /* -p ... */
675 fwd_r_add_sport(x, r->src_port); /* --sport ... */
676 fwd_r_add_dport(x, r->src_dport); /* --dport ... */
677 fwd_r_add_srcmac(x, r->src_mac); /* -m mac --mac-source ... */
678 fwd_r_add_dnattarget(x, r->dest_ip, r->dest_port); /* -j DNAT ... */
679 fwd_r_add_comment(x, "redir", z, n); /* -m comment ... */
680 fwd_xt_append_rule(x, "redirects"); /* -A redirects */
684 if( (x = fwd_xt_init_rule(h_filter)) != NULL )
686 fwd_xt_parse_in(x, n, 0); /* -i ... */
687 fwd_xt_parse_src(x, r->src_ip, 0); /* -s ... */
688 fwd_xt_parse_dest(x, r->dest_ip, 0); /* -d ... */
689 fwd_xt_parse_proto(x, r->proto, 0); /* -p ... */
690 fwd_r_add_srcmac(x, r->src_mac); /* -m mac --mac-source ... */
691 fwd_r_add_sport(x, r->src_port); /* --sport ... */
692 fwd_r_add_dport(x, r->dest_port); /* --dport ... */
693 fwd_r_add_policytarget(x, FWD_P_ACCEPT); /* -j handle_accept */
694 fwd_r_add_comment(x, "redir", z, n); /* -m comment ... */
695 fwd_xt_append_rule(x, "redirects"); /* -A redirects */
698 /* Add loopback rule if neither src_ip nor src_mac are defined */
699 if( !r->src_ip && !r->src_mac )
701 if( (x = fwd_xt_init_rule(h_nat)) != NULL )
703 fwd_xt_parse_in(x, n, 1); /* -i ! ... */
704 fwd_xt_parse_dest(x, r->dest_ip, 0); /* -d ... */
705 fwd_xt_parse_proto(x, r->proto, 0); /* -p ... */
706 fwd_r_add_sport(x, r->src_port); /* --sport ... */
707 fwd_r_add_dport(x, r->src_dport); /* --dport ... */
708 fwd_xt_get_target(x, "MASQUERADE"); /* -j MASQUERADE */
709 fwd_r_add_comment(x, "redir", z, n); /* -m comment ... */
710 fwd_xt_append_rule(x, "loopback"); /* -A loopback */
716 for( e = z->rules; e && (c = &e->section.rule); e = e->next )
718 /* Has destination, add forward rule for each network in target zone */
721 for( n2 = c->dest->networks; n2; n2 = n2->next )
723 printf("\n# Net %s (%s) - rule+dest"
724 " Z:%s N:%s I:%s -> Z:%s N:%s I:%s\n",
725 n->name, n->ifname, z->name, n->name, n->ifname,
726 f->dest->name, n2->name, n2->ifname);
728 if( (x = fwd_xt_init_rule(h_filter)) != NULL )
730 fwd_xt_parse_in(x, n, 0); /* -i ... */
731 fwd_xt_parse_out(x, n2, 0); /* -o ... */
732 fwd_xt_parse_src(x, c->src_ip, 0); /* -s ... */
733 fwd_xt_parse_dest(x, c->dest_ip, 0); /* -d ... */
734 fwd_xt_parse_proto(x, c->proto, 0); /* -p ... */
735 fwd_r_add_icmptype(x, c->icmp_type); /* --icmp-type ... */
736 fwd_r_add_srcmac(x, c->src_mac); /* --mac-source ... */
737 fwd_r_add_sport(x, c->src_port); /* --sport ... */
738 fwd_r_add_dport(x, c->dest_port); /* --dport ... */
739 fwd_r_add_policytarget(x, c->target); /* -j handle_... */
740 fwd_r_add_comment(x, "rule", z, n); /* -m comment ... */
741 fwd_xt_append_rule(x, "rules"); /* -A rules */
746 /* No destination specified, treat it as input rule */
749 printf("\n# Net %s (%s) - rule Z:%s N:%s I:%s\n",
750 n->name, n->ifname, z->name, n->name, n->ifname);
752 if( (x = fwd_xt_init_rule(h_filter)) != NULL )
754 fwd_xt_parse_in(x, n, 0); /* -i ... */
755 fwd_xt_parse_src(x, c->src_ip, 0); /* -s ... */
756 fwd_xt_parse_dest(x, c->dest_ip, 0); /* -d ... */
757 fwd_xt_parse_proto(x, c->proto, 0); /* -p ... */
758 fwd_r_add_icmptype(x, c->icmp_type); /* --icmp-type ... */
759 fwd_r_add_srcmac(x, c->src_mac); /* --mac-source ... */
760 fwd_r_add_sport(x, c->src_port); /* --sport ... */
761 fwd_r_add_dport(x, c->dest_port); /* --dport ... */
762 fwd_r_add_policytarget(x, c->target); /* -j handle_... */
763 fwd_r_add_comment(x, "rule", z, n); /* -m comment ... */
764 fwd_xt_append_rule(x, "rules"); /* -A rules */
769 if( !iptc_commit(h_nat) )
770 fwd_fatal("Cannot commit nat table: %s", iptc_strerror(errno));
772 if( !iptc_commit(h_filter) )
773 fwd_fatal("Cannot commit filter table: %s", iptc_strerror(errno));
780 static void fwd_ipt_delif_table(struct iptc_handle *h, const char *net)
782 const struct xt_entry_match *m;
783 const struct ipt_entry *e;
784 const char *chain, *comment;
785 size_t off = 0, num = 0;
788 for( chain = iptc_first_chain(h); chain;
789 chain = iptc_next_chain(h)
792 for( e = iptc_first_rule(chain, h), num = 0; e;
793 e = iptc_next_rule(e, h), num++
797 /* skip entries w/o matches */
798 if( ! e->target_offset )
801 /* iterate matches */
802 for( off = sizeof(struct ipt_entry);
803 off < e->target_offset;
804 off += m->u.match_size
809 if( ! strcmp(m->u.user.name, "comment") )
811 /* better use struct_xt_comment_info but well... */
812 comment = (void *)m + sizeof(struct xt_entry_match);
814 if( fwd_r_cmp("net=", comment, net) )
816 e = iptc_next_rule(e, h);
817 iptc_delete_num_entry(chain, num, h);
830 void fwd_ipt_delif(struct fwd_handle *h, const char *net)
832 struct iptc_handle *h_filter, *h_nat;
834 if( !(h_filter = iptc_init("filter")) || !(h_nat = iptc_init("nat")) )
835 fwd_fatal("Unable to obtain libiptc handle");
838 printf("\n\n#\n# delif(%s)\n#\n", net);
840 /* delete network related rules */
841 fwd_ipt_delif_table(h_nat, net);
842 fwd_ipt_delif_table(h_filter, net);
845 if( !iptc_commit(h_nat) )
846 fwd_fatal("Cannot commit nat table: %s", iptc_strerror(errno));
848 if( !iptc_commit(h_filter) )
849 fwd_fatal("Cannot commit filter table: %s", iptc_strerror(errno));
855 void fwd_ipt_chgif(struct fwd_handle *h, const char *net)
857 /* XXX: should alter rules in-place, tbd */
858 fwd_ipt_delif(h, net);
859 fwd_ipt_addif(h, net);
863 static void fwd_ipt_clear_ruleset_table(struct iptc_handle *h)
867 /* pass 1: flush all chains */
868 for( chain = iptc_first_chain(h); chain;
869 chain = iptc_next_chain(h)
871 iptc_flush_entries(chain, h);
874 /* pass 2: remove user defined chains */
875 for( chain = iptc_first_chain(h); chain;
876 chain = iptc_next_chain(h)
878 if( ! iptc_builtin(chain, h) )
879 iptc_delete_chain(chain, h);
883 void fwd_ipt_clear_ruleset(struct fwd_handle *h)
885 struct iptc_handle *h_filter, *h_nat;
887 if( !(h_filter = iptc_init("filter")) || !(h_nat = iptc_init("nat")) )
888 fwd_fatal("Unable to obtain libiptc handle");
891 fwd_ipt_clear_ruleset_table(h_nat);
892 fwd_ipt_clear_ruleset_table(h_filter);
894 /* revert policies */
895 fwd_r_set_policy(h_filter, "INPUT", "ACCEPT");
896 fwd_r_set_policy(h_filter, "OUTPUT", "ACCEPT");
897 fwd_r_set_policy(h_filter, "FORWARD", "ACCEPT");
900 if( !iptc_commit(h_nat) )
901 fwd_fatal("Cannot commit nat table: %s", iptc_strerror(errno));
903 if( !iptc_commit(h_filter) )
904 fwd_fatal("Cannot commit filter table: %s", iptc_strerror(errno));