case 'ipv4_addr':
ip = filter(this.parse_subnet(values[i]), a => (a.family == 4));
- switch (length(ip)) {
+ switch (length(ip) ?? 0) {
case 0: return null;
case 1: break;
default: this.warn("Set entry '%s' resolves to multiple addresses, using first one", values[i]);
}
},
+ l4proto: function(family, proto) {
+ switch (proto.name) {
+ case 'icmp':
+ switch (family ?? 0) {
+ case 0:
+ return this.set(['icmp', 'ipv6-icmp']);
+
+ case 6:
+ return 'ipv6-icmp';
+ }
+
+ default:
+ return proto.name;
+ }
+ },
+
datetime: function(stamp) {
return sprintf('"%04d-%02d-%02d %02d:%02d:%02d"',
stamp.year, stamp.month, stamp.day,
// we need to emit one or two AF specific rules
else {
- if (family_is_ipv4(zone) && length(match_subnets[0]))
+ if (!family || family == 4)
for (let subnets in subnets_group_by_masking(match_subnets[0]))
add_rule(4, devgroup, subnets, zone);
- if (family_is_ipv6(zone) && length(match_subnets[1]))
+ if (!family || family == 6)
for (let subnets in subnets_group_by_masking(match_subnets[1]))
add_rule(6, devgroup, subnets, zone);
}
}
else if (need_src_action_chain(r)) {
r.jump_chain = sprintf("%s_from_%s", r.target, r.src.zone.name);
- r.src.zone.dflags[r.target] = true;
+ r.src.zone.sflags[r.target] = true;
}
else if (r.target == "reject")
r.jump_chain = "handle_reject";
if (length(rip[0]) > 1 || length(rip[1]) > 1)
this.warn_section(data, "specifies multiple rewrite addresses, using only first one");
+ let has_ip4_addr = length(sip[0]) || length(dip[0]) || length(rip[0]),
+ has_ip6_addr = length(sip[1]) || length(dip[1]) || length(rip[1]),
+ has_any_addr = has_ip4_addr || has_ip6_addr;
+
/* check if there's no AF specific bits, in this case we can do an AF agnostic rule */
- if (!family && !length(sip[0]) && !length(sip[1]) && !length(dip[0]) && !length(dip[1]) && !length(rip[0]) && !length(rip[1])) {
+ if (!family && !has_any_addr) {
/* for backwards compatibility, treat unspecified family as IPv4 unless user explicitly requested any (0) */
if (family == null)
family = 4;
/* we need to emit one or two AF specific rules */
else {
- if ((!family || family == 4) && (length(sip[0]) || length(dip[0]) || length(rip[0]))) {
+ if ((!family || family == 4) && (!has_any_addr || has_ip4_addr)) {
for (let saddrs in subnets_group_by_masking(sip[0]))
for (let daddrs in subnets_group_by_masking(dip[0]))
add_rule(4, proto, saddrs, daddrs, rip[0], sport, dport, rport, ipset, redir);
}
- if ((!family || family == 6) && (length(sip[1]) || length(dip[1]) || length(rip[1]))) {
+ if ((!family || family == 6) && (!has_any_addr || has_ip6_addr)) {
for (let saddrs in subnets_group_by_masking(sip[1]))
for (let daddrs in subnets_group_by_masking(dip[1]))
add_rule(6, proto, saddrs, daddrs, rip[1], sport, dport, rport, ipset, redir);
enabled: [ "bool", "1" ],
name: [ "string", this.section_id(data[".name"]) ],
- family: [ "family", "4" ],
+ family: [ "family" ],
src: [ "zone_ref" ],
device: [ "string" ],
return;
}
- if (snat.src && snat.src.zone)
- snat.src.zone.dflags.snat = true;
-
let add_rule = (family, proto, saddrs, daddrs, raddrs, sport, dport, rport, snat) => {
let n = {
...snat,
if (length(rip[0]) > 1 || length(rip[1]) > 1)
this.warn_section(data, "specifies multiple rewrite addresses, using only first one");
- /* inherit family restrictions from related zones */
- if (family === 0 || family === null) {
- let f = (rule.src && rule.src.zone) ? rule.src.zone.family : 0;
-
- if (f) {
- this.warn_section(r,
- sprintf("inheriting %s restriction from src %s",
- this.nfproto(f1, true), rule.src.zone.name));
+ family = infer_family(family, [
+ sip, "source IP",
+ dip, "destination IP",
+ rip, "rewrite IP",
+ snat.src?.zone, "source zone"
+ ]);
- family = f;
- }
+ if (type(family) == "string") {
+ this.warn_section(data, family + ", skipping");
+ continue;
}
+ if (snat.src?.zone)
+ snat.src.zone.dflags.snat = true;
+
/* if no family was configured, infer target family from IP addresses */
if (family === null) {
if ((length(sip[0]) || length(dip[0]) || length(rip[0])) && !length(sip[1]) && !length(dip[1]) && !length(rip[1]))
else if ((length(sip[1]) || length(dip[1]) || length(rip[1])) && !length(sip[0]) && !length(dip[0]) && !length(rip[0]))
family = 6;
else
- family = 0;
+ family = 4; /* default to IPv4 only for backwards compatibility, unless an explict family any was configured */
}
/* check if there's no AF specific bits, in this case we can do an AF agnostic rule */