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);
401 static void fwd_ipt_defaults_create(struct fwd_data *d)
403 struct fwd_defaults *def = &d->section.defaults;
404 struct iptc_handle *h_filter, *h_nat;
406 if( !(h_filter = iptc_init("filter")) || !(h_nat = iptc_init("nat")) )
407 fwd_fatal("Unable to obtain libiptc handle");
410 fwd_r_set_policy(h_filter, "INPUT",
411 def->input == FWD_P_ACCEPT ? "ACCEPT" : "DROP");
412 fwd_r_set_policy(h_filter, "OUTPUT",
413 def->output == FWD_P_ACCEPT ? "ACCEPT" : "DROP");
414 fwd_r_set_policy(h_filter, "FORWARD",
415 def->forward == FWD_P_ACCEPT ? "ACCEPT" : "DROP");
417 /* invalid state drop */
418 if( def->drop_invalid )
420 fwd_r_drop_invalid(h_filter, "INPUT");
421 fwd_r_drop_invalid(h_filter, "OUTPUT");
422 fwd_r_drop_invalid(h_filter, "FORWARD");
425 /* default accept related */
426 fwd_r_accept_related(h_filter, "INPUT");
427 fwd_r_accept_related(h_filter, "OUTPUT");
428 fwd_r_accept_related(h_filter, "FORWARD");
430 /* default accept on lo */
431 fwd_r_accept_lo(h_filter);
433 /* syn flood protection */
436 fwd_r_add_synflood(h_filter, def);
439 /* rule container chains */
440 fwd_r_new_chain(h_filter, "mssfix");
441 fwd_r_new_chain(h_filter, "zones");
442 fwd_r_new_chain(h_filter, "rules");
443 fwd_r_new_chain(h_filter, "redirects");
444 fwd_r_new_chain(h_filter, "forwardings");
445 fwd_r_jump_chain(h_filter, "INPUT", "rules");
446 fwd_r_jump_chain(h_filter, "FORWARD", "mssfix");
447 fwd_r_jump_chain(h_filter, "FORWARD", "zones");
448 fwd_r_jump_chain(h_filter, "FORWARD", "rules");
449 fwd_r_jump_chain(h_filter, "FORWARD", "redirects");
450 fwd_r_jump_chain(h_filter, "FORWARD", "forwardings");
451 fwd_r_new_chain(h_nat, "zonemasq");
452 fwd_r_new_chain(h_nat, "redirects");
453 fwd_r_new_chain(h_nat, "loopback");
454 fwd_r_jump_chain(h_nat, "POSTROUTING", "zonemasq");
455 fwd_r_jump_chain(h_nat, "PREROUTING", "redirects");
456 fwd_r_jump_chain(h_nat, "POSTROUTING", "loopback");
458 /* standard drop, accept, reject chain */
459 fwd_r_handle_drop(h_filter);
460 fwd_r_handle_accept(h_filter);
461 fwd_r_handle_reject(h_filter);
464 if( !iptc_commit(h_nat) )
465 fwd_fatal("Cannot commit nat table: %s", iptc_strerror(errno));
467 if( !iptc_commit(h_filter) )
468 fwd_fatal("Cannot commit filter table: %s", iptc_strerror(errno));
475 void fwd_ipt_build_ruleset(struct fwd_handle *h)
481 for( e = h->conf; e; e = e->next )
486 printf("\n## DEFAULTS\n");
487 fwd_ipt_defaults_create(e);
491 printf("\n## INCLUDE %s\n", e->section.include.path);
505 static struct fwd_zone *
506 fwd_lookup_zone(struct fwd_handle *h, const char *net)
509 struct fwd_network_list *n;
511 for( e = h->conf; e; e = e->next )
512 if( e->type == FWD_S_ZONE )
513 for( n = e->section.zone.networks; n; n = n->next )
514 if( !strcmp(n->name, net) )
515 return &e->section.zone;
520 static struct fwd_network_list *
521 fwd_lookup_network(struct fwd_zone *z, const char *net)
523 struct fwd_network_list *n;
525 for( n = z->networks; n; n = n->next )
526 if( !strcmp(n->name, net) )
532 static struct fwd_addr_list *
533 fwd_lookup_addr(struct fwd_handle *h, struct fwd_network_list *n)
535 struct fwd_addr_list *a;
538 for( a = h->addrs; a; a = a->next )
539 if( !strcmp(a->ifname, n->ifname) )
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_addr_list *a, *a2;
553 struct fwd_network_list *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 = fwd_lookup_addr(h, n)) )
575 printf("\n\n#\n# addif(%s)\n#\n", net);
577 /* Build masquerading rule */
580 printf("\n# Net %s (%s) - masq\n", n->name, n->ifname);
582 if( (x = fwd_xt_init_rule(h_nat)) != NULL )
584 fwd_xt_parse_out(x, n, 0); /* -o ... */
585 fwd_xt_get_target(x, "MASQUERADE"); /* -j MASQUERADE */
586 fwd_r_add_comment(x, "masq", z, NULL, n); /* -m comment ... */
587 fwd_xt_exec_rule(x, "zonemasq"); /* -A zonemasq */
591 /* Build MSS fix rule */
594 printf("\n# Net %s (%s) - mtu_fix\n", n->name, n->ifname);
596 if( (x = fwd_xt_init_rule(h_filter)) != NULL )
599 fwd_xt_parse_out(x, n, 0); /* -o ... */
600 fwd_xt_parse_proto(x, &p, 0); /* -p tcp */
602 /* -m tcp --tcp-flags SYN,RST SYN */
603 if( (m = fwd_xt_get_match(x, "tcp")) != NULL )
604 fwd_xt_parse_match(x, m, "--tcp-flags", "SYN,RST", "SYN");
606 /* -j TCPMSS --clamp-mss-to-pmtu */
607 if( (t = fwd_xt_get_target(x, "TCPMSS")) != NULL )
608 fwd_xt_parse_target(x, t, "--clamp-mss-to-pmtu");
611 fwd_r_add_comment(x, "mssfix", z, NULL, n);
614 fwd_xt_exec_rule(x, "mssfix");
618 /* Build intra-zone forwarding rules */
619 for( n2 = z->networks; n2; n2 = n2->next )
621 if( (a2 = fwd_lookup_addr(h, n2)) != NULL )
623 printf("\n# Net %s (%s) - intra-zone-forwarding"
624 " Z:%s N:%s I:%s -> Z:%s N:%s I:%s\n",
625 n->name, n->ifname, z->name, n->name, n->ifname,
626 z->name, n2->name, n2->ifname);
628 if( (x = fwd_xt_init_rule(h_filter)) != NULL )
630 fwd_xt_parse_in(x, n, 0); /* -i ... */
631 fwd_xt_parse_out(x, n2, 0); /* -o ... */
632 fwd_r_add_policytarget(x, z->forward); /* -j handle_... */
633 fwd_r_add_comment(x, "zone", z, n, n2); /* -m comment ... */
634 fwd_xt_exec_rule(x, "zones"); /* -A zones */
639 /* Build inter-zone forwarding rules */
640 for( e = z->forwardings; e && (f = &e->section.forwarding); e = e->next )
642 for( n2 = f->dest->networks; n2; n2 = n2->next )
644 printf("\n# Net %s (%s) - inter-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 f->dest->name, n2->name, n2->ifname);
649 /* Build forwarding rule */
650 if( (x = fwd_xt_init_rule(h_filter)) != NULL )
652 fwd_xt_parse_in(x, n, 0); /* -i ... */
653 fwd_xt_parse_out(x, n2, 0); /* -o ... */
654 fwd_r_add_policytarget(x, FWD_P_ACCEPT); /* -j handle_... */
655 fwd_r_add_comment(x, "forward", z, n, n2); /* -m comment ... */
656 fwd_xt_exec_rule(x, "forwardings"); /* -A forwardings */
661 /* Build DNAT rules */
662 for( e = z->redirects; e && (r = &e->section.redirect); e = e->next )
664 printf("\n# Net %s (%s) - redirect Z:%s N:%s I:%s\n",
665 n->name, n->ifname, z->name, n->name, n->ifname);
668 if( (x = fwd_xt_init_rule(h_nat)) != NULL )
670 fwd_xt_parse_in(x, n, 0); /* -i ... */
671 fwd_xt_parse_src(x, r->src_ip, 0); /* -s ... */
672 fwd_xt_parse_dest(x, &a->ipaddr, 0); /* -d ... */
673 fwd_xt_parse_proto(x, r->proto, 0); /* -p ... */
674 fwd_r_add_sport(x, r->src_port); /* --sport ... */
675 fwd_r_add_dport(x, r->src_dport); /* --dport ... */
676 fwd_r_add_srcmac(x, r->src_mac); /* -m mac --mac-source ... */
677 fwd_r_add_dnattarget(x, r->dest_ip, r->dest_port); /* -j DNAT ... */
678 fwd_r_add_comment(x, "redir", z, n, NULL); /* -m comment ... */
679 fwd_xt_exec_rule(x, "redirects"); /* -A redirects */
683 if( (x = fwd_xt_init_rule(h_filter)) != NULL )
685 fwd_xt_parse_in(x, n, 0); /* -i ... */
686 fwd_xt_parse_src(x, r->src_ip, 0); /* -s ... */
687 fwd_xt_parse_dest(x, r->dest_ip, 0); /* -d ... */
688 fwd_xt_parse_proto(x, r->proto, 0); /* -p ... */
689 fwd_r_add_srcmac(x, r->src_mac); /* -m mac --mac-source ... */
690 fwd_r_add_sport(x, r->src_port); /* --sport ... */
691 fwd_r_add_dport(x, r->dest_port); /* --dport ... */
692 fwd_r_add_policytarget(x, FWD_P_ACCEPT); /* -j handle_accept */
693 fwd_r_add_comment(x, "redir", z, n, NULL); /* -m comment ... */
694 fwd_xt_exec_rule(x, "redirects"); /* -A redirects */
697 /* Add loopback rule if neither src_ip nor src_mac are defined */
698 if( !r->src_ip && !r->src_mac )
700 if( (x = fwd_xt_init_rule(h_nat)) != NULL )
702 fwd_xt_parse_in(x, n, 1); /* -i ! ... */
703 fwd_xt_parse_dest(x, r->dest_ip, 0); /* -d ... */
704 fwd_xt_parse_proto(x, r->proto, 0); /* -p ... */
705 fwd_r_add_sport(x, r->src_port); /* --sport ... */
706 fwd_r_add_dport(x, r->src_dport); /* --dport ... */
707 fwd_xt_get_target(x, "MASQUERADE"); /* -j MASQUERADE */
708 fwd_r_add_comment(x, "redir", z, n, NULL); /* -m comment ... */
709 fwd_xt_exec_rule(x, "loopback"); /* -A loopback */
715 for( e = z->rules; e && (c = &e->section.rule); e = e->next )
717 /* Has destination, add forward rule for each network in target zone */
720 for( n2 = c->dest->networks; n2; n2 = n2->next )
722 printf("\n# Net %s (%s) - rule+dest"
723 " Z:%s N:%s I:%s -> Z:%s N:%s I:%s\n",
724 n->name, n->ifname, z->name, n->name, n->ifname,
725 f->dest->name, n2->name, n2->ifname);
727 if( (x = fwd_xt_init_rule(h_filter)) != NULL )
729 fwd_xt_parse_in(x, n, 0); /* -i ... */
730 fwd_xt_parse_out(x, n2, 0); /* -o ... */
731 fwd_xt_parse_src(x, c->src_ip, 0); /* -s ... */
732 fwd_xt_parse_dest(x, c->dest_ip, 0); /* -d ... */
733 fwd_xt_parse_proto(x, c->proto, 0); /* -p ... */
734 fwd_r_add_icmptype(x, c->icmp_type); /* --icmp-type ... */
735 fwd_r_add_srcmac(x, c->src_mac); /* --mac-source ... */
736 fwd_r_add_sport(x, c->src_port); /* --sport ... */
737 fwd_r_add_dport(x, c->dest_port); /* --dport ... */
738 fwd_r_add_policytarget(x, c->target); /* -j handle_... */
739 fwd_r_add_comment(x, "rule", z, n, n2); /* -m comment ... */
740 fwd_xt_exec_rule(x, "rules"); /* -A rules */
745 /* No destination specified, treat it as input rule */
748 printf("\n# Net %s (%s) - rule Z:%s N:%s I:%s\n",
749 n->name, n->ifname, z->name, n->name, n->ifname);
751 if( (x = fwd_xt_init_rule(h_filter)) != NULL )
753 fwd_xt_parse_in(x, n, 0); /* -i ... */
754 fwd_xt_parse_src(x, c->src_ip, 0); /* -s ... */
755 fwd_xt_parse_dest(x, c->dest_ip, 0); /* -d ... */
756 fwd_xt_parse_proto(x, c->proto, 0); /* -p ... */
757 fwd_r_add_icmptype(x, c->icmp_type); /* --icmp-type ... */
758 fwd_r_add_srcmac(x, c->src_mac); /* --mac-source ... */
759 fwd_r_add_sport(x, c->src_port); /* --sport ... */
760 fwd_r_add_dport(x, c->dest_port); /* --dport ... */
761 fwd_r_add_policytarget(x, c->target); /* -j handle_... */
762 fwd_r_add_comment(x, "rule", z, n, NULL); /* -m comment ... */
763 fwd_xt_exec_rule(x, "rules"); /* -A rules */
768 if( !iptc_commit(h_nat) )
769 fwd_fatal("Cannot commit nat table: %s", iptc_strerror(errno));
771 if( !iptc_commit(h_filter) )
772 fwd_fatal("Cannot commit filter table: %s", iptc_strerror(errno));