- if ($dest) {
- if ($dest =~ m/^\+/) {
- if ($dest =~ m/^\+(${ipset_name_pattern})$/) {
- my $name = $1;
- if ($fw_conf && $fw_conf->{ipset}->{$name}) {
- my $ipset_chain = compute_ipset_chain_name($fw_conf->{vmid}, $name, $ipversion);
- push @cmd, "-m set --match-set ${ipset_chain} dst";
- } elsif ($cluster_conf && $cluster_conf->{ipset}->{$name}) {
- my $ipset_chain = compute_ipset_chain_name(0, $name, $ipversion);
- push @cmd, "-m set --match-set ${ipset_chain} dst";
+ return $match;
+}
+
+# convert a %rule to an array of iptables commands
+sub ipt_rule_to_cmds {
+ my ($rule, $chain, $ipversion, $cluster_conf, $fw_conf, $vmid) = @_;
+
+ die "ipt_rule_to_cmds unable to handle macro" if $rule->{macro}; #should not happen
+
+ my @match = ();
+
+ if (defined $rule->{match}) {
+ push @match, $rule->{match};
+ } else {
+ push @match, "-i $rule->{iface_in}" if $rule->{iface_in};
+ push @match, "-o $rule->{iface_out}" if $rule->{iface_out};
+
+ if ($rule->{source}) {
+ push @match, ipt_gen_src_or_dst_match($rule->{source}, 's', $ipversion, $cluster_conf, $fw_conf);
+ }
+ if ($rule->{dest}) {
+ push @match, ipt_gen_src_or_dst_match($rule->{dest}, 'd', $ipversion, $cluster_conf, $fw_conf);
+ }
+
+ if (my $proto = $rule->{proto}) {
+ push @match, "-p $proto";
+
+ my $nbdport = defined($rule->{dport}) ? parse_port_name_number_or_range($rule->{dport}, 1) : 0;
+ my $nbsport = defined($rule->{sport}) ? parse_port_name_number_or_range($rule->{sport}, 0) : 0;
+
+ my $multiport = 0;
+ $multiport++ if $nbdport > 1;
+ $multiport++ if $nbsport > 1;
+
+ push @match, "--match multiport" if $multiport;
+
+ die "multiport: option '--sports' cannot be used together with '--dports'\n"
+ if ($multiport == 2) && ($rule->{dport} ne $rule->{sport});
+
+ if ($rule->{dport}) {
+ if ($proto eq 'icmp') {
+ # Note: we use dport to store --icmp-type
+ die "unknown icmp-type '$rule->{dport}'\n"
+ if $rule->{dport} !~ /^\d+$/ && !defined($icmp_type_names->{$rule->{dport}});
+ push @match, "-m icmp --icmp-type $rule->{dport}";
+ } elsif ($proto eq 'icmpv6') {
+ # Note: we use dport to store --icmpv6-type
+ die "unknown icmpv6-type '$rule->{dport}'\n"
+ if $rule->{dport} !~ /^\d+$/ && !defined($icmpv6_type_names->{$rule->{dport}});
+ push @match, "-m icmpv6 --icmpv6-type $rule->{dport}";
+ } elsif (!$PROTOCOLS_WITH_PORTS->{$proto}) {
+ die "protocol $proto does not have ports\n";