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 fwd_ipt_rule_append(struct fwd_ipt_rulebuf
*r
, const char *fmt
, ...)
29 char buf
[256]; buf
[0] = 0;
33 len
= vsnprintf(buf
, sizeof(buf
), fmt
, ap
);
38 r
->buf
= realloc(r
->buf
, r
->len
+ len
+ 1);
39 memcpy(&r
->buf
[r
->len
], buf
, len
);
40 r
->buf
[r
->len
+ len
] = 0;
45 static struct fwd_ipt_rulebuf
* fwd_ipt_init(const char *table
)
47 struct fwd_ipt_rulebuf
*r
;
49 if( (r
= fwd_alloc_ptr(struct fwd_ipt_rulebuf
)) != NULL
)
51 fwd_ipt_rule_append(r
, IPT
" -t %s", table
);
58 static void fwd_ipt_add_srcport(
59 struct fwd_ipt_rulebuf
*r
, struct fwd_portrange
*p
64 fwd_ipt_rule_append(r
, " --sport %u:%u", p
->min
, p
->max
);
66 fwd_ipt_rule_append(r
, " --sport %u", p
->min
);
70 static void fwd_ipt_add_destport(
71 struct fwd_ipt_rulebuf
*r
, struct fwd_portrange
*p
76 fwd_ipt_rule_append(r
, " --dport %u:%u", p
->min
, p
->max
);
78 fwd_ipt_rule_append(r
, " --dport %u", p
->min
);
82 static void fwd_ipt_add_proto(
83 struct fwd_ipt_rulebuf
*r
, struct fwd_proto
*p
90 fwd_ipt_rule_append(r
, " -p tcp -p udp");
94 fwd_ipt_rule_append(r
, " -p tcp");
98 fwd_ipt_rule_append(r
, " -p udp");
102 fwd_ipt_rule_append(r
, " -p icmp");
106 fwd_ipt_rule_append(r
, " -p all");
110 fwd_ipt_rule_append(r
, " -p %u", p
->proto
);
116 static void fwd_ipt_add_srcaddr(
117 struct fwd_ipt_rulebuf
*r
, struct fwd_cidr
*c
122 fwd_ipt_rule_append(r
, " -s %s/%u",
123 inet_ntoa(c
->addr
), c
->prefix
);
125 fwd_ipt_rule_append(r
, " -s %s", inet_ntoa(c
->addr
));
129 static void fwd_ipt_add_destaddr(
130 struct fwd_ipt_rulebuf
*r
, struct fwd_cidr
*c
135 fwd_ipt_rule_append(r
, " -d %s/%u",
136 inet_ntoa(c
->addr
), c
->prefix
);
138 fwd_ipt_rule_append(r
, " -d %s", inet_ntoa(c
->addr
));
142 static void fwd_ipt_add_srcmac(
143 struct fwd_ipt_rulebuf
*r
, struct fwd_mac
*m
147 fwd_ipt_rule_append(r
,
148 " -m mac --mac-source %02x:%02x:%02x:%02x:%02x:%02x",
149 m
->mac
[0], m
->mac
[1], m
->mac
[2],
150 m
->mac
[3], m
->mac
[4], m
->mac
[5]);
154 static void fwd_ipt_add_icmptype(
155 struct fwd_ipt_rulebuf
*r
, struct fwd_icmptype
*i
160 fwd_ipt_rule_append(r
, " --icmp-type %s", i
->name
);
161 else if( i
->code
> -1 )
162 fwd_ipt_rule_append(r
, " --icmp-type %u/%u", i
->type
, i
->code
);
164 fwd_ipt_rule_append(r
, " --icmp-type %u", i
->type
);
168 static void fwd_ipt_add_dnat_target(
169 struct fwd_ipt_rulebuf
*r
, struct fwd_cidr
*c
, struct fwd_portrange
*p
173 fwd_ipt_rule_append(r
, " -j DNAT --to-destination %s",
176 if( (p
!= NULL
) && (p
->min
< p
->max
) )
177 fwd_ipt_rule_append(r
, ":%u-%u", p
->min
, p
->max
);
179 fwd_ipt_rule_append(r
, ":%u", p
->min
);
183 static void fwd_ipt_add_policy_target(
184 struct fwd_ipt_rulebuf
*r
, enum fwd_policy p
186 fwd_ipt_rule_append(r
, " -j %s",
189 : (p
== FWD_P_REJECT
)
195 static void fwd_ipt_add_comment(
196 struct fwd_ipt_rulebuf
*r
, const char *t
, struct fwd_zone
*z
,
197 struct fwd_network_list
*n
, struct fwd_network_list
*n2
199 if( (n
!= NULL
) && (n2
!= NULL
) )
200 fwd_ipt_add_format(r
, " -m comment --comment '%s:%s src:%s dest:%s'",
201 t
, z
->name
, n
->name
, n2
->name
);
202 else if( (n
== NULL
) && (n2
!= NULL
) )
203 fwd_ipt_add_format(r
, " -m comment --comment '%s:%s dest:%s'",
204 t
, z
->name
, n2
->name
);
206 fwd_ipt_add_format(r
, " -m comment --comment '%s:%s src:%s'",
207 t
, z
->name
, n
->name
);
210 static void fwd_ipt_exec(struct fwd_ipt_rulebuf
*r
)
213 printf("%s\n", r
->buf
);
215 fwd_free_ptr(r
->buf
);
219 /* -P <chain> <policy> */
220 static void fwd_r_set_policy(
221 struct iptc_handle
*h
, const char *chain
, const char *policy
223 iptc_set_policy(chain
, policy
, NULL
, h
);
227 static void fwd_r_new_chain(struct iptc_handle
*h
, const char *chain
)
229 iptc_create_chain(chain
, h
);
232 /* -A <chain1> -j <chain2> */
233 static void fwd_r_jump_chain(
234 struct iptc_handle
*h
, const char *chain1
, const char *chain2
236 struct fwd_xt_rule
*r
;
238 if( (r
= fwd_xt_init_rule(h
)) != NULL
)
240 fwd_xt_get_target(r
, chain2
);
241 fwd_xt_exec_rule(r
, chain1
);
245 /* -A <chain> -m state --state INVALID -j DROP */
246 static void fwd_r_drop_invalid(struct iptc_handle
*h
, const char *chain
)
248 struct fwd_xt_rule
*r
;
249 struct xtables_match
*m
;
251 if( (r
= fwd_xt_init_rule(h
)) != NULL
)
253 if( (m
= fwd_xt_get_match(r
, "state")) != NULL
)
255 fwd_xt_parse_match(r
, m
, "--state", "INVALID", 0);
256 fwd_xt_get_target(r
, "DROP");
257 fwd_xt_exec_rule(r
, chain
);
262 /* -A <chain> -m state --state RELATED,ESTABLISHED -j ACCEPT */
263 static void fwd_r_accept_related(struct iptc_handle
*h
, const char *chain
)
265 struct fwd_xt_rule
*r
;
266 struct xtables_match
*m
;
268 if( (r
= fwd_xt_init_rule(h
)) != NULL
)
270 if( (m
= fwd_xt_get_match(r
, "state")) != NULL
)
272 fwd_xt_parse_match(r
, m
, "--state", "RELATED,ESTABLISHED", 0);
273 fwd_xt_get_target(r
, "ACCEPT");
274 fwd_xt_exec_rule(r
, chain
);
279 /* -A INPUT -i lo -j ACCEPT; -A OUTPUT -o lo -j ACCEPT */
280 static void fwd_r_accept_lo(struct iptc_handle
*h
)
282 struct fwd_network_list n
;
283 struct fwd_xt_rule
*r
;
287 if( (r
= fwd_xt_init_rule(h
)) != NULL
)
289 fwd_xt_parse_in(r
, &n
, 0);
290 fwd_xt_get_target(r
, "ACCEPT");
291 fwd_xt_exec_rule(r
, "INPUT");
294 if( (r
= fwd_xt_init_rule(h
)) != NULL
)
296 fwd_xt_parse_out(r
, &n
, 0);
297 fwd_xt_get_target(r
, "ACCEPT");
298 fwd_xt_exec_rule(r
, "OUTPUT");
302 /* build syn_flood chain and jump rule */
303 static void fwd_r_add_synflood(struct iptc_handle
*h
, struct fwd_defaults
*def
)
306 struct fwd_xt_rule
*r
;
307 struct xtables_match
*m
;
311 fwd_r_new_chain(h
, "syn_flood");
314 if( (r
= fwd_xt_init_rule(h
)) != NULL
)
318 fwd_xt_parse_proto(r
, &p
, 0);
321 if( (m
= fwd_xt_get_match(r
, "tcp")) != NULL
)
323 fwd_xt_parse_match(r
, m
, "--syn", NULL
, 0);
326 /* -m limit --limit x/second --limit-burst y */
327 if( (m
= fwd_xt_get_match(r
, "limit")) != NULL
)
329 sprintf(buf
, "%i/second", def
->syn_rate
);
330 fwd_xt_parse_match(r
, m
, "--limit", buf
, 0);
332 sprintf(buf
, "%i", def
->syn_burst
);
333 fwd_xt_parse_match(r
, m
, "--limit-burst", buf
, 0);
336 /* -j RETURN; -A syn_flood */
337 fwd_xt_get_target(r
, "RETURN");
338 fwd_xt_exec_rule(r
, "syn_flood");
342 if( (r
= fwd_xt_init_rule(h
)) != NULL
)
344 /* -j DROP; -A syn_flood */
345 fwd_xt_get_target(r
, "DROP");
346 fwd_xt_exec_rule(r
, "syn_flood");
349 /* jump to syn_flood rule */
350 if( (r
= fwd_xt_init_rule(h
)) != NULL
)
354 fwd_xt_parse_proto(r
, &p
, 0);
357 if( (m
= fwd_xt_get_match(r
, "tcp")) != NULL
)
359 fwd_xt_parse_match(r
, m
, "--syn", NULL
, 0);
362 /* -j syn_flood; -A INPUT */
363 fwd_xt_get_target(r
, "syn_flood");
364 fwd_xt_exec_rule(r
, "INPUT");
368 /* build reject target chain */
369 static void fwd_r_handle_reject(struct iptc_handle
*h
)
372 struct fwd_xt_rule
*r
;
373 struct xtables_target
*t
;
375 /* -N handle_reject */
376 fwd_r_new_chain(h
, "handle_reject");
378 /* tcp reject rule */
379 if( (r
= fwd_xt_init_rule(h
)) != NULL
)
383 fwd_xt_parse_proto(r
, &p
, 0);
385 /* -j REJECT --reject-with tcp-reset */
386 if( (t
= fwd_xt_get_target(r
, "REJECT")) != NULL
)
388 fwd_xt_parse_target(r
, t
, "--reject-with", "tcp-reset", 0);
391 /* -A handle_reject */
392 fwd_xt_exec_rule(r
, "handle_reject");
395 /* common reject rule */
396 if( (r
= fwd_xt_init_rule(h
)) != NULL
)
398 /* -j REJECT --reject-with icmp-port-unreachable */
399 if( (t
= fwd_xt_get_target(r
, "REJECT")) != NULL
)
401 fwd_xt_parse_target(r
, t
, "--reject-with",
402 "icmp-port-unreachable", 0);
405 /* -A handle_reject */
406 fwd_xt_exec_rule(r
, "handle_reject");
410 /* build drop target chain */
411 static void fwd_r_handle_drop(struct iptc_handle
*h
)
413 struct fwd_xt_rule
*r
;
416 fwd_r_new_chain(h
, "handle_drop");
418 /* common drop rule */
419 if( (r
= fwd_xt_init_rule(h
)) != NULL
)
421 /* -j DROP; -A handle_reject */
422 fwd_xt_get_target(r
, "DROP");
423 fwd_xt_exec_rule(r
, "handle_reject");
427 /* build accept target chain */
428 static void fwd_r_handle_accept(struct iptc_handle
*h
)
430 struct fwd_xt_rule
*r
;
432 /* -N handle_accept */
433 fwd_r_new_chain(h
, "handle_accept");
435 /* common accept rule */
436 if( (r
= fwd_xt_init_rule(h
)) != NULL
)
438 /* -j ACCEPT; -A handle_accept */
439 fwd_xt_get_target(r
, "ACCEPT");
440 fwd_xt_exec_rule(r
, "handle_accept");
445 static void fwd_ipt_defaults_create(struct fwd_data
*d
)
447 struct fwd_defaults
*def
= &d
->section
.defaults
;
448 struct iptc_handle
*h_filter
, *h_nat
;
450 if( !(h_filter
= iptc_init("filter")) || !(h_nat
= iptc_init("nat")) )
451 fwd_fatal("Unable to obtain libiptc handle");
454 fwd_r_set_policy(h_filter
, "INPUT",
455 def
->input
== FWD_P_ACCEPT
? "ACCEPT" : "DROP");
456 fwd_r_set_policy(h_filter
, "OUTPUT",
457 def
->output
== FWD_P_ACCEPT
? "ACCEPT" : "DROP");
458 fwd_r_set_policy(h_filter
, "FORWARD",
459 def
->forward
== FWD_P_ACCEPT
? "ACCEPT" : "DROP");
461 /* invalid state drop */
462 if( def
->drop_invalid
)
464 fwd_r_drop_invalid(h_filter
, "INPUT");
465 fwd_r_drop_invalid(h_filter
, "OUTPUT");
466 fwd_r_drop_invalid(h_filter
, "FORWARD");
469 /* default accept related */
470 fwd_r_accept_related(h_filter
, "INPUT");
471 fwd_r_accept_related(h_filter
, "OUTPUT");
472 fwd_r_accept_related(h_filter
, "FORWARD");
474 /* default accept on lo */
475 fwd_r_accept_lo(h_filter
);
477 /* syn flood protection */
480 fwd_r_add_synflood(h_filter
, def
);
483 /* rule container chains */
484 fwd_r_new_chain(h_filter
, "mssfix");
485 fwd_r_new_chain(h_filter
, "zones");
486 fwd_r_new_chain(h_filter
, "rules");
487 fwd_r_new_chain(h_filter
, "redirects");
488 fwd_r_new_chain(h_filter
, "forwardings");
489 fwd_r_jump_chain(h_filter
, "INPUT", "rules");
490 fwd_r_jump_chain(h_filter
, "FORWARD", "mssfix");
491 fwd_r_jump_chain(h_filter
, "FORWARD", "zones");
492 fwd_r_jump_chain(h_filter
, "FORWARD", "rules");
493 fwd_r_jump_chain(h_filter
, "FORWARD", "redirects");
494 fwd_r_jump_chain(h_filter
, "FORWARD", "forwardings");
495 fwd_r_new_chain(h_nat
, "zonemasq");
496 fwd_r_new_chain(h_nat
, "redirects");
497 fwd_r_jump_chain(h_nat
, "POSTROUTING", "zonemasq");
498 fwd_r_jump_chain(h_nat
, "PREROUTING", "redirects");
499 fwd_r_jump_chain(h_nat
, "POSTROUTING", "redirects");
501 /* standard drop, accept, reject chain */
502 fwd_r_handle_drop(h_filter
);
503 fwd_r_handle_accept(h_filter
);
504 fwd_r_handle_reject(h_filter
);
507 if( !iptc_commit(h_nat
) )
508 fwd_fatal("Cannot commit nat table: %s", iptc_strerror(errno
));
510 if( !iptc_commit(h_filter
) )
511 fwd_fatal("Cannot commit filter table: %s", iptc_strerror(errno
));
518 void fwd_ipt_build_ruleset(struct fwd_handle
*h
)
524 for( e
= h
->conf
; e
; e
= e
->next
)
529 printf("\n## DEFAULTS\n");
530 fwd_ipt_defaults_create(e
);
534 printf("\n## INCLUDE %s\n", e
->section
.include
.path
);
548 static struct fwd_zone
*
549 fwd_lookup_zone(struct fwd_handle
*h
, const char *net
)
552 struct fwd_network_list
*n
;
554 for( e
= h
->conf
; e
; e
= e
->next
)
555 if( e
->type
== FWD_S_ZONE
)
556 for( n
= e
->section
.zone
.networks
; n
; n
= n
->next
)
557 if( !strcmp(n
->name
, net
) )
558 return &e
->section
.zone
;
563 static struct fwd_network_list
*
564 fwd_lookup_network(struct fwd_zone
*z
, const char *net
)
566 struct fwd_network_list
*n
;
568 for( n
= z
->networks
; n
; n
= n
->next
)
569 if( !strcmp(n
->name
, net
) )
575 static struct fwd_addr_list
*
576 fwd_lookup_addr(struct fwd_handle
*h
, struct fwd_network_list
*n
)
578 struct fwd_addr_list
*a
;
581 for( a
= h
->addrs
; a
; a
= a
->next
)
582 if( !strcmp(a
->ifname
, n
->ifname
) )
588 void fwd_ipt_addif(struct fwd_handle
*h
, const char *net
)
592 struct fwd_ipt_rulebuf
*b
;
594 struct fwd_redirect
*r
;
595 struct fwd_forwarding
*f
;
596 struct fwd_addr_list
*a
, *a2
;
597 struct fwd_network_list
*n
, *n2
;
599 if( !(z
= fwd_lookup_zone(h
, net
)) )
602 if( !(n
= fwd_lookup_network(z
, net
)) )
605 if( !(a
= fwd_lookup_addr(h
, n
)) )
608 printf("\n\n#\n# addif(%s)\n#\n", net
);
610 /* Build masquerading rule */
613 printf("\n# Net %s (%s) - masq\n", n
->name
, n
->ifname
);
615 b
= fwd_ipt_init("nat");
616 fwd_ipt_add_format(b
, " -A zonemasq -o %s -j MASQUERADE", n
->ifname
);
617 fwd_ipt_add_comment(b
, "masq", z
, NULL
, n
);
621 /* Build MSS fix rule */
624 printf("\n# Net %s (%s) - mtu_fix\n", n
->name
, n
->ifname
);
626 b
= fwd_ipt_init("filter");
627 fwd_ipt_add_format(b
,
628 " -A mssfix -o %s -p tcp --tcp-flags SYN,RST SYN"
629 " -j TCPMSS --clamp-mss-to-pmtu", n
->ifname
);
630 fwd_ipt_add_comment(b
, "mssfix", z
, NULL
, n
);
634 /* Build intra-zone forwarding rules */
635 for( n2
= z
->networks
; n2
; n2
= n2
->next
)
637 if( (a2
= fwd_lookup_addr(h
, n2
)) != NULL
)
639 printf("\n# Net %s (%s) - intra-zone-forwarding"
640 " Z:%s N:%s I:%s -> Z:%s N:%s I:%s\n",
641 n
->name
, n
->ifname
, z
->name
, n
->name
, n
->ifname
,
642 z
->name
, n2
->name
, n2
->ifname
);
644 b
= fwd_ipt_init("filter");
645 fwd_ipt_add_format(b
, " -A zones -i %s -o %s",
646 n
->ifname
, n2
->ifname
);
647 fwd_ipt_add_policy_target(b
, z
->forward
);
648 fwd_ipt_add_comment(b
, "zone", z
, n
, n2
);
653 /* Build inter-zone forwarding rules */
654 for( e
= z
->forwardings
; e
&& (f
= &e
->section
.forwarding
); e
= e
->next
)
656 for( n2
= f
->dest
->networks
; n2
; n2
= n2
->next
)
658 printf("\n# Net %s (%s) - inter-zone-forwarding"
659 " Z:%s N:%s I:%s -> Z:%s N:%s I:%s\n",
660 n
->name
, n
->ifname
, z
->name
, n
->name
, n
->ifname
,
661 f
->dest
->name
, n2
->name
, n2
->ifname
);
663 /* Build forwarding rule */
664 b
= fwd_ipt_init("filter");
665 fwd_ipt_add_format(b
, " -A forwardings -i %s -o %s",
666 n
->ifname
, n2
->ifname
);
667 fwd_ipt_add_policy_target(b
, FWD_P_ACCEPT
);
668 fwd_ipt_add_comment(b
, "forward", z
, n
, n2
);
673 /* Build DNAT rules */
674 for( e
= z
->redirects
; e
&& (r
= &e
->section
.redirect
); e
= e
->next
)
676 printf("\n# Net %s (%s) - redirect Z:%s N:%s I:%s\n",
677 n
->name
, n
->ifname
, z
->name
, n
->name
, n
->ifname
);
680 b
= fwd_ipt_init("nat");
681 fwd_ipt_add_format(b
, " -A redirects -i %s -d %s",
682 n
->ifname
, inet_ntoa(a
->ipaddr
.v4
));
683 fwd_ipt_add_proto(b
, r
->proto
);
684 fwd_ipt_add_srcaddr(b
, r
->src_ip
);
685 fwd_ipt_add_srcport(b
, r
->src_port
);
686 fwd_ipt_add_destport(b
, r
->src_dport
);
687 fwd_ipt_add_srcmac(b
, r
->src_mac
);
688 fwd_ipt_add_dnat_target(b
, r
->dest_ip
, r
->dest_port
);
689 fwd_ipt_add_comment(b
, "redir", z
, n
, NULL
);
693 b
= fwd_ipt_init("filter");
694 fwd_ipt_add_format(b
, " -A redirects -i %s", n
->ifname
);
695 fwd_ipt_add_proto(b
, r
->proto
);
696 fwd_ipt_add_srcmac(b
, r
->src_mac
);
697 fwd_ipt_add_srcaddr(b
, r
->src_ip
);
698 fwd_ipt_add_srcport(b
, r
->src_port
);
699 fwd_ipt_add_destaddr(b
, r
->dest_ip
);
700 fwd_ipt_add_destport(b
, r
->dest_port
);
701 fwd_ipt_add_policy_target(b
, FWD_P_ACCEPT
);
702 fwd_ipt_add_comment(b
, "redir", z
, n
, NULL
);
705 /* Add loopback rule if neither src_ip nor src_mac are defined */
706 if( !r
->src_ip
&& !r
->src_mac
)
708 b
= fwd_ipt_init("nat");
709 fwd_ipt_add_format(b
, " -A redirects -i ! %s -d %s",
710 n
->ifname
, inet_ntoa(r
->dest_ip
->addr
));
711 fwd_ipt_add_proto(b
, r
->proto
);
712 fwd_ipt_add_srcport(b
, r
->src_port
);
713 fwd_ipt_add_destport(b
, r
->src_dport
);
714 fwd_ipt_add_format(b
, " -j MASQUERADE");
715 fwd_ipt_add_comment(b
, "redir", z
, n
, NULL
);
721 for( e
= z
->rules
; e
&& (c
= &e
->section
.rule
); e
= e
->next
)
723 /* Has destination, add forward rule for each network in target zone */
726 for( n2
= c
->dest
->networks
; n2
; n2
= n2
->next
)
728 printf("\n# Net %s (%s) - rule+dest"
729 " Z:%s N:%s I:%s -> Z:%s N:%s I:%s\n",
730 n
->name
, n
->ifname
, z
->name
, n
->name
, n
->ifname
,
731 f
->dest
->name
, n2
->name
, n2
->ifname
);
733 b
= fwd_ipt_init("filter");
734 fwd_ipt_add_format(b
, " -A rules -i %s -o %s",
735 n
->ifname
, n2
->ifname
);
736 fwd_ipt_add_proto(b
, c
->proto
);
737 fwd_ipt_add_icmptype(b
, c
->icmp_type
);
738 fwd_ipt_add_srcmac(b
, c
->src_mac
);
739 fwd_ipt_add_srcaddr(b
, c
->src_ip
);
740 fwd_ipt_add_srcport(b
, c
->src_port
);
741 fwd_ipt_add_destaddr(b
, c
->dest_ip
);
742 fwd_ipt_add_destport(b
, c
->dest_port
);
743 fwd_ipt_add_policy_target(b
, c
->target
);
744 fwd_ipt_add_comment(b
, "rule", z
, n
, n2
);
749 /* No destination specified, treat it as input rule */
752 printf("\n# Net %s (%s) - rule Z:%s N:%s I:%s\n",
753 n
->name
, n
->ifname
, z
->name
, n
->name
, n
->ifname
);
755 b
= fwd_ipt_init("filter");
756 fwd_ipt_add_format(b
, " -A rules -i %s", n
->ifname
);
757 fwd_ipt_add_proto(b
, c
->proto
);
758 fwd_ipt_add_icmptype(b
, c
->icmp_type
);
759 fwd_ipt_add_srcmac(b
, c
->src_mac
);
760 fwd_ipt_add_srcaddr(b
, c
->src_ip
);
761 fwd_ipt_add_srcport(b
, c
->src_port
);
762 fwd_ipt_add_destaddr(b
, c
->dest_ip
);
763 fwd_ipt_add_destport(b
, c
->dest_port
);
764 fwd_ipt_add_policy_target(b
, c
->target
);
765 fwd_ipt_add_comment(b
, "rule", z
, n
, n2
);