fw4.uc: fix zone helper assignment
[project/firewall4.git] / root / usr / share / ucode / fw4.uc
index 12e0d8cfe2e092d94c60599da19e0dbb88b9358d..a3384466538fe1298da55611b6294527f46bc7c7 100644 (file)
@@ -131,14 +131,19 @@ const dscp_classes = {
 };
 
 function to_mask(bits, v6) {
-       let m = [];
+       let m = [], n = false;
 
-       if (bits < 0 || bits > (v6 ? 128 : 32))
+       if (bits < 0) {
+               n = true;
+               bits = -bits;
+       }
+
+       if (bits > (v6 ? 128 : 32))
                return null;
 
        for (let i = 0; i < (v6 ? 16 : 4); i++) {
                let b = (bits < 8) ? bits : 8;
-               m[i] = (0xff << (8 - b)) & 0xff;
+               m[i] = (n ? ~(0xff << (8 - b)) : (0xff << (8 - b))) & 0xff;
                bits -= b;
        }
 
@@ -333,11 +338,11 @@ function map_setmatch(set, match, proto) {
 
                switch (t) {
                case 'ipv4_addr':
-                       fields[i] = `ip ${dir}saddr`;
+                       fields[i] = `ip ${dir}addr`;
                        break;
 
                case 'ipv6_addr':
-                       fields[i] = `ip6 ${dir}saddr`;
+                       fields[i] = `ip6 ${dir}addr`;
                        break;
 
                case 'ether_addr':
@@ -356,53 +361,33 @@ function map_setmatch(set, match, proto) {
        return fields;
 }
 
-function determine_device_type(devname) {
-       let uevent = fs.open(`/sys/class/net/${devname}/uevent`),
-           devtype = null;
-
-       if (uevent) {
-               let line;
-
-               while ((line = uevent.read('line')) != null) {
-                       let m = match(line, /^DEVTYPE=(\w+)/);
-
-                       if (m) {
-                               devtype = m[1];
-                               break;
-                       }
-               }
-
-               uevent.close();
-       }
+function resolve_lower_devices(devstatus, devname, require_hwoffload) {
+       let dir = fs.opendir(`/sys/class/net/${devname}`);
+       let devs = [];
 
-       return devtype;
-}
-
-function resolve_lower_devices(devname) {
-       switch (determine_device_type(devname)) {
-       case null:
-               return [];
-
-       case 'vlan':
-       case 'bridge':
-               let dir = fs.opendir(`/sys/class/net/${devname}`);
-               let lower = [];
-
-               if (dir) {
+       if (dir) {
+               switch (devstatus[devname]?.devtype) {
+               case 'vlan':
+               case 'bridge':
                        let e;
 
                        while ((e = dir.read()) != null)
                                if (index(e, "lower_") === 0)
-                                       push(lower, ...resolve_lower_devices(substr(e, 6)));
+                                       push(devs, ...resolve_lower_devices(devstatus, substr(e, 6), require_hwoffload));
 
-                       dir.close();
-               }
+                       break;
 
-               return lower;
+               default:
+                       if (!require_hwoffload || devstatus[devname]?.["hw-tc-offload"])
+                               push(devs, devname);
 
-       default:
-               return [ devname ];
+                       break;
+               }
+
+               dir.close();
        }
+
+       return devs;
 }
 
 function nft_json_command(...args) {
@@ -460,24 +445,39 @@ return {
        },
 
        resolve_offload_devices: function() {
+               if (!this.default_option("flow_offloading"))
+                       return [];
+
+               let devstatus = null;
                let devices = [];
+               let bus = ubus.connect();
+
+               if (bus) {
+                       devstatus = bus.call("network.device", "status") || {};
+                       bus.disconnect();
+               }
 
-               if (this.default_option("flow_offloading")) {
+               if (this.default_option("flow_offloading_hw")) {
                        for (let zone in this.zones())
                                for (let device in zone.related_physdevs)
-                                       push(devices, ...resolve_lower_devices(device));
+                                       push(devices, ...resolve_lower_devices(devstatus, device, true));
 
-                       if (length(devices)) {
-                               devices = sort(uniq(devices));
+                       devices = sort(uniq(devices));
 
-                               if (this.default_option("flow_offloading_hw") && !nft_try_hw_offload(devices)) {
-                                       this.warn('Hardware flow offloading unavailable, falling back to software offloading');
-                                       this.state.defaults.flow_offloading_hw = false;
-                               }
-                       }
+                       if (length(devices) && nft_try_hw_offload(devices))
+                               return devices;
+
+                       this.warn('Hardware flow offloading unavailable, falling back to software offloading');
+                       this.state.defaults.flow_offloading_hw = false;
+
+                       devices = [];
                }
 
-               return devices;
+               for (let zone in this.zones())
+                       for (let device in zone.related_physdevs)
+                               push(devices, ...resolve_lower_devices(devstatus, device, false));
+
+               return sort(uniq(devices));
        },
 
        check_set_types: function() {
@@ -838,6 +838,7 @@ return {
                                        return null;
 
                                m = to_mask(b, length(a) == 16);
+                               b = max(-1, b);
                        }
 
                        return [{
@@ -1237,26 +1238,21 @@ return {
        },
 
        parse_date: function(val) {
-               let m = match(val, /^([0-9-]+)T([0-9:]+)$/);
-               let d = m ? match(m[1], /^([0-9]{1,4})(-([0-9]{1,2})(-([0-9]{1,2}))?)?$/) : null;
-               let t = this.parse_time(m[2]);
-
-               d[3] ||= 1;
-               d[5] ||= 1;
+               let d = match(val, /^([0-9]{4})(-([0-9]{1,2})(-([0-9]{1,2})(T([0-9:]+))?)?)?$/);
 
-               if (d == null || d[1] < 1970 || d[1] > 2038 || d[3] < 1 || d[3] > 12 || d[5] < 1 || d[5] > 31)
+               if (d == null || d[1] < 1970 || d[1] > 2038 || d[3] > 12 || d[5] > 31)
                        return null;
 
-               if (m[2] && !t)
+               let t = this.parse_time(d[7] ?? "0");
+
+               if (t == null)
                        return null;
 
                return {
                        year:  +d[1],
-                       month: +d[3],
-                       day:   +d[5],
-                       hour:  t ? +t[1] : 0,
-                       min:   t ? +t[3] : 0,
-                       sec:   t ? +t[5] : 0
+                       month: +d[3] || 1,
+                       day:   +d[5] || 1,
+                       ...t
                };
        },
 
@@ -1642,6 +1638,10 @@ return {
                return sprintf('"%04d-%02d-%02d"', stamp.year, stamp.month, stamp.day);
        },
 
+       datestamp: function(stamp) {
+               return exists(stamp, 'hour') ? this.datetime(stamp) : this.date(stamp);
+       },
+
        time: function(stamp) {
                return sprintf('"%02d:%02d:%02d"', stamp.hour, stamp.min, stamp.sec);
        },
@@ -1881,9 +1881,12 @@ return {
                        this.warn_section(data, "is disabled, ignoring section");
                        return;
                }
-               else if (zone.helper && !zone.helper.available) {
-                       this.warn_section(data, `uses unavailable ct helper '${zone.helper.name}', ignoring section`);
-                       return;
+
+               for (let helper in zone.helper) {
+                       if (!helper.available) {
+                               this.warn_section(data, `uses unavailable ct helper '${zone.helper.name}', ignoring section`);
+                               return;
+                       }
                }
 
                if (zone.mtu_fix && this.kernel < 0x040a0000) {
@@ -1905,7 +1908,9 @@ return {
                                push(related_ubus_networks, { invert: false, device: name });
                }
 
-               for (let e in [ ...to_array(zone.network), ...related_ubus_networks ]) {
+               zone.network = [ ...to_array(zone.network), ...related_ubus_networks ];
+
+               for (let e in zone.network) {
                        if (exists(this.state.networks, e.device)) {
                                let net = this.state.networks[e.device];