diff --git a/_javascript/filter_tool.js b/_javascript/filter_tool.js index c2a078b1..55ffa794 100644 --- a/_javascript/filter_tool.js +++ b/_javascript/filter_tool.js @@ -214,6 +214,7 @@ pathPrefix: "", sender: "", tempRadio: "any", + via: "radio", verdict: "continue", scopeGate: "unchanged", targetKind: "scope", @@ -257,6 +258,8 @@ pathKind: enumValue(input.pathKind, PATH_KINDS, "Path matcher", "none"), pathPrefix: "", sender: clean(input.sender), + via: enumValue(input.via === "cross,bridge" ? "bridge,cross" : input.via, + ["radio", "bridge", "cross", "bridge,cross"], "Traffic path", "radio"), tempRadio: enumValue(input.tempRadio, ["any", "active", "inactive"], "Temporary-radio matcher", "any"), verdict: enumValue(input.verdict, ["continue", "drop"], "Forwarding verdict", "continue"), scopeGate: enumValue(input.scopeGate, ["unchanged", "require_allowed", "bypass_global"], "Scope-gate action", "unchanged"), @@ -356,6 +359,7 @@ if (rule.pathKind === "prefix") matches.push(`path=prefix:${rule.pathPrefix}`); else if (rule.pathKind !== "none") matches.push(`path=${rule.pathKind}`); if (rule.sender) matches.push(`sender=${quoteDsl(rule.sender)}`); + if (rule.via !== "radio") matches.push(`via=${rule.via}`); if (rule.tempRadio !== "any") matches.push(`tempradio=${rule.tempRadio}`); const actions = []; if (rule.verdict === "drop") actions.push("drop"); @@ -464,6 +468,7 @@ rule.pathPrefix = value.slice(7); } else rule.pathKind = value; } else if (name === "sender") rule.sender = value; + else if (name === "via") rule.via = value; else if (name === "tempradio") rule.tempRadio = value; else throw new FilterToolError(`Unsupported receive-time matcher: ${token}`); }); @@ -564,6 +569,7 @@ else if (rule.pathKind.startsWith("bucket:")) conditions.push(`a path matching ${rule.pathKind}`); else if (rule.pathKind.startsWith("loop:")) conditions.push(`the ${rule.pathKind.slice(5)} own-ID loop threshold`); if (rule.sender) conditions.push(`decrypted sender "${rule.sender}"`); + conditions.push(`traffic path ${rule.via}`); if (rule.tempRadio !== "any") conditions.push(`temporary radio ${rule.tempRadio}`); const mode = rule.mode === "shadow" ? "In shadow mode, report that it would " @@ -970,6 +976,7 @@ regionName: clean(input.regionName), sender, tempRadio: Boolean(input.tempRadio), + via: enumValue(input.via, ["radio", "bridge", "cross"], "Packet traffic path", "radio"), blacklist: Boolean(input.blacklist), buckets: Array.from(new Set(buckets)), loopLevel: requiredInteger(input.loopLevel == null ? 0 : input.loopLevel, 0, 3, "Loop result"), @@ -1002,6 +1009,7 @@ const rule = normalizeRule(inputRule); const packet = normalizePacket(inputPacket); const misses = []; + if (!rule.via.split(",").includes(packet.via)) misses.push(`traffic path is ${packet.via}`); if (rule.route === "flood" && !["unscoped_flood", "scoped_flood"].includes(packet.route)) misses.push("route is not flood"); else if (rule.route !== "flood" && rule.route !== packet.route) misses.push(`route is ${packet.route}`); if (!typeMatches(rule.type, packet.type)) misses.push(`payload type ${packet.type} is outside ${rule.type}`); @@ -1228,6 +1236,12 @@ owner: "system", channel: "#wardriving", }, + { + ...documentedDropRule("wardriving-bridge-cross", "any", "all", 220), + owner: "system", + channel: "#wardriving", + via: "bridge,cross", + }, ]), }); @@ -1302,6 +1316,7 @@ pathPrefix: field("path-prefix").value, sender: field("sender").value, tempRadio: field("temp-radio").value, + via: field("via").value, verdict: field("verdict").value, scopeGate: field("scope-gate").value, targetKind: field("target-kind").value, @@ -1335,6 +1350,7 @@ "path-prefix": rule.pathPrefix, sender: rule.sender, "temp-radio": rule.tempRadio, + via: rule.via, verdict: rule.verdict, "scope-gate": rule.scopeGate, "target-kind": rule.targetKind, @@ -1564,6 +1580,7 @@ regionName: packetField("region-name").value, sender: packetField("sender").value, tempRadio: packetField("temp-radio").checked, + via: packetField("via").value, blacklist: packetField("blacklist").value === "yes", buckets: packetField("buckets").value, loopLevel: packetField("loop-level").value, diff --git a/cli_commands/index.html b/cli_commands/index.html index 7aee45ce..30a4db0f 100644 --- a/cli_commands/index.html +++ b/cli_commands/index.html @@ -821,6 +821,28 @@ + + +
  • + + + + Set Companion TX routing per contact or channel + + + + +
  • + +
  • + + + + Set repeater, room-server, and sensor reply profiles + + + +
  • @@ -1650,6 +1672,17 @@ +
  • + +
  • + + + + Bridge and radio crossover filters + + + +
  • @@ -5203,6 +5236,28 @@ +
  • + +
  • + + + + Set Companion TX routing per contact or channel + + + + +
  • + +
  • + + + + Set repeater, room-server, and sensor reply profiles + + + +
  • @@ -6032,6 +6087,17 @@ +
  • + +
  • + + + + Bridge and radio crossover filters + + + +
  • @@ -7723,6 +7789,43 @@ When a page has no fixes, its origin is 0,0, origin index is differentials are 0,0. Values outside -8192 through 8191 are clipped and set flag bit 0.


    +

    Set Companion TX routing per contact or channel

    +
    set tx.user "Alice Jones" radio2
    +get tx.user "Alice Jones"
    +set tx.channel 0 both
    +get tx.channel 0
    +set tx.channel #wardriving radio
    +
    +

    Both command families accept auto, radio, radio2, both, or off. +auto uses the global crossing rules. Explicit choices override +radio2.cross, but radio2 must still be enabled in rxtx to transmit there. +radio2 never falls back to the primary profile; both uses whichever of its +selected profiles can transmit. Set a target back to auto to remove its +override.

    +

    Use an exact contact/channel name, a zero-based channel index, or +key:<12-64 hex digits> for a unique contact public-key prefix. Duplicate +names/prefixes are rejected. get tx.user and get tx.channel show override +counts; queries with a target show its saved choice and current effective +profile selection. Choices are saved with the contact/channel and work for +phone-app and terminal messages. A contact's off setting also blocks its +ACKs and addressed responses.

    +

    See Companion routing details and examples +for temporary profiles, persistence, and the traffic covered by each setting.

    +

    Set repeater, room-server, and sensor reply profiles

    +
    get tx.reply
    +set tx.reply both
    +set tx.reply both force
    +set tx.reply radio
    +set tx.reply auto
    +
    +

    Persistent choices: auto, radio, radio2, both (default), and off. +Explicit choices override radio2.cross for local replies, including CLI, +ACKs, telemetry, room subscription posts, and served LoRa OTA responses. +Append force to both or radio2 to permit reply TX on an active RX-only +second profile. It never enables a disabled profile or ordinary forwarding. +Omitting force removes that override. off suppresses remote replies too.

    +

    See reply routing and OTA examples +for temporary profiles, receive-only exceptions, and queued reply handling.

    Set Companion display rotation

    SSD1306 Full Companion builds support a persisted runtime orientation:

    get display.rotation
    @@ -9182,6 +9285,54 @@ managed row with ~data. Flood group text (GRP_TXT) is
     setting.

    get flood.channel.data includes the active hop gate as h=all or h>N.


    +

    Bridge and radio crossover filters

    +

    mode= selects where a generalized flood.rule / flood.filter row applies:

    + + + + + + + + + + + + + + + + + + + + + + + + + +
    ModeWhere the rule applies
    radioOrdinary LoRa flood forwarding. This is the default when mode= is omitted.
    bridgePackets entering or leaving an RS232 or ESP-NOW bridge, and MeshCore RX/TX packet publication through MQTT.
    crossTransmissions copied to the other radio profile, including a copy's retries. The same-profile transmission remains eligible.
    bridge,crossBoth transport paths using one rule. cross,bridge is equivalent.
    +

    The third built-in repeater rule blocks authenticated #wardriving text and +data at all hops on bridge and crossover paths, including temporary-radio +sessions. It leaves same-profile traffic subject to the separate four-hop +rule. set radio2.cross on does not override this filter.

    +
    # Factory slot: inspect before replacing an existing rule.
    +get flood.rule.3
    +set flood.rule.3 type=any channel=#wardriving hops=all mode=bridge,cross drop
    +# On an existing device, add it without overwriting an occupied slot.
    +set flood.rule type=any channel=#wardriving hops=all mode=bridge,cross drop
    +
    +

    Saved tables are preserved on upgrade; new defaults are seeded only when the +table is first initialized. Bridge/cross modes accept drop, rate, priority and +stop actions; scope rewrites, retry actions and TX timing are rejected. +These modes cover direct as well as flood packets, in both crossing directions. +The default authenticates the channel key, avoiding false drops from short +channel-hash collisions. FULL room servers support explicit transport rules; +companions and compact FPF6 profiles do not expose this table.

    +

    See filtering documentation +for persistence, queue/rate semantics, exceptions, and how to remove one or +both blocks.

    Block selected flood channels with FPF7

    The separate flood.channel.block command and 15-row table have been retired. Generalized repeaters use the 63-row FPF7 forward phase for authenticated channel @@ -9421,44 +9572,54 @@ get flood.channel.scope.require.1

    Change persistent flood rules in the field

    For setup guidance, interactions with the existing forwarding controls, and worked moderation examples, see Flood Filtering and Moderation.

    -

    Usage: -- get flood.rule -- get flood.rule.<n> -- set flood.rule[.<n>] type=<type> [hops=<range>] [channel=<channel>] [prefix=<path-prefix>] [in=<input-scope>] <drop|scope=<name>|region=<name>|rate=<N>/min|retry|stop> [priority=<0-255>] [tx=slow] [suspend=tempradio] -- del flood.rule.<n> -- del flood.rule all -- get flood.filter -- get flood.filter.<n> -- get flood.filter.blacklist -- get flood.filter.blacklist.<n> -- set flood.filter.blacklist <ID[,ID...]> -- set flood.filter.blacklist.<n> <ID[,ID...]> -- del flood.filter.blacklist -- del flood.filter.blacklist.<n> -- set flood.filter <type> [hops] [path=blacklist] [scope=<name>] [require=region] [tx=slow] [suspend=tempradio] -- set flood.filter.<n> <type> [hops] [path=blacklist] [scope=<name>] [require=region] [tx=slow] [suspend=tempradio] -- del flood.filter.<n> -- del flood.filter all

    +

    Usage:

    +
      +
    • get flood.rule
    • +
    • get flood.rule.<n>
    • +
    • get fr[.<n>] (numbered form returns a complete short setter for copying)
    • +
    • set fr[.<n>] <type> [h=<range>] [m=r|b|c|bc] [c=<channel>] <d|s=<scope>|r=<region>|q=<N>|r|s> [...]
    • +
    • del fr.<n> or del fr all
    • +
    • set flood.rule[.<n>] type=<type> [mode=radio|bridge|cross|bridge,cross] [hops=<range>] [channel=<channel>] [prefix=<path-prefix>] [in=<input-scope>] <drop|scope=<name>|region=<name>|rate=<N>/min|retry|stop> [priority=<0-255>] [tx=slow] [suspend=tempradio]
    • +
    • del flood.rule.<n>
    • +
    • del flood.rule all
    • +
    • get flood.filter
    • +
    • get flood.filter.<n>
    • +
    • get flood.filter.blacklist
    • +
    • get flood.filter.blacklist.<n>
    • +
    • set flood.filter.blacklist <ID[,ID...]>
    • +
    • set flood.filter.blacklist.<n> <ID[,ID...]>
    • +
    • del flood.filter.blacklist
    • +
    • del flood.filter.blacklist.<n>
    • +
    • set flood.filter <type> [hops] [path=blacklist] [scope=<name>] [require=region] [tx=slow] [suspend=tempradio]
    • +
    • set flood.filter.<n> <type> [hops] [path=blacklist] [scope=<name>] [require=region] [tx=slow] [suspend=tempradio]
    • +
    • del flood.filter.<n>
    • +
    • del flood.filter all
    • +

    The extended table is available on repeaters with the rule engine enabled and -on FULL-profile ESP32 room servers. A FULL room server exposes both -flood.rule and flood.filter, has 31 slots, and requires an administrator +on FULL-profile ESP32 room servers. A FULL room server exposes +fr, flood.rule, and flood.filter, has 31 slots, and requires an administrator for remote changes. It does not have the repeater's passive path blacklist, so flood.filter.blacklist* and path=blacklist are repeater-only; use the ordered prefix= match on a room server. Standard room-server profiles do not compile this table.

    -

    Parameters: -- n: Forward-rule slot in the build's compiled table (1-63 on generalized - repeaters and 1-31 on FULL room servers; compact profiles may use fewer). -- type: Payload type name, full PAYLOAD_TYPE_* name, decimal value 0-15, - hexadecimal value 0x00-0x0F, or any. -- hops: Optional; omitted means all. - - N: Match only at received hop count N. - - N+: Match at received hop count N and higher. - - N-M: Match the inclusive received-hop range. - - all: Match every received hop count (0-63). - - 0+, all, and an omitted hop expression are equivalent. The CLI displays - the saved range as all. -- channel=*|public|#name|hash:XX|128-bit-key|256-bit-key: Optional channel match. +

    Parameters:

    +
      +
    • n: Forward-rule slot in the build's compiled table (1-63 on generalized + repeaters and 1-31 on FULL room servers; compact profiles may use fewer).
    • +
    • mode: Optional; omitted means radio. bridge filters bridge admission, + cross filters copies to the other radio profile, and bridge,cross covers + both with one row. cross,bridge is an alias. See the + mode matrix for scope and supported actions.
    • +
    • type: Payload type name, full PAYLOAD_TYPE_* name, decimal value 0-15, + hexadecimal value 0x00-0x0F, or any.
    • +
    • hops: Optional; omitted means all.
    • +
    • N: Match only at received hop count N.
    • +
    • N+: Match at received hop count N and higher.
    • +
    • N-M: Match the inclusive received-hop range.
    • +
    • all: Match every received hop count (0-63).
    • +
    • 0+, all, and an omitted hop expression are equivalent. The CLI displays + the saved range as all.
    • +
    • channel=*|public|#name|hash:XX|128-bit-key|256-bit-key: Optional channel match. channel=* means no channel condition at all, so the row matches everything selected by type= (including all flood payload types with type=any). It does not authenticate a packet. public, #name, and raw keys authenticate @@ -9472,65 +9633,66 @@ compile this table.

      or deliberately selected 0x11 value. channel=public performs the deeper MAC/decrypt check with the Public channel key. That distinguishes an ordinary 0x11 collision, but it is channel authentication rather than sender - authentication: the group MAC is two bytes and the Public key is shared. -- prefix=<ID[,ID...]>: Optional ordered source-path prefix of one to three + authentication: the group MAC is two bytes and the Public key is shared.
    • +
    • prefix=<ID[,ID...]>: Optional ordered source-path prefix of one to three pbyte IDs. IDs must all be 2, 4, or 6 hex characters, matching a packet's - 1-, 2-, or 3-byte pbyte width. path=<prefix> is an alias. -- in=any|none|scoped|allowed|unknown|scope:<name>|region:<name>: Optional + 1-, 2-, or 3-byte pbyte width. path=<prefix> is an alias.
    • +
    • in=any|none|scoped|allowed|unknown|scope:<name>|region:<name>: Optional condition on the original incoming scope, before any rule rewrites it. none is an unscoped flood. scope:name is the exact public - hashtag-derived scope. region:name is an exact allowed region match. -- drop: Explicit drop action. The flood.rule form requires an explicit + hashtag-derived scope. region:name is an exact allowed region match.
    • +
    • drop: Explicit drop action. The flood.rule form requires an explicit action. For compatibility, a legacy flood.filter row with no rewrite, - rate, or stop action is treated as drop. -- scope=<name>: Direct public-name scope rewrite. It derives a transport key + rate, or stop action is treated as drop.
    • +
    • scope=<name>: Direct public-name scope rewrite. It derives a transport key from the name and does not require a configured region. For example, scope=BlackHole86 is a regionless sink scope; region=BlackHole86 would - instead require a real configured, flood-allowed region with that name. -- region=<name>: Rewrite using an existing locally allowed region and one of - that region's transport keys. -- rate=N/min: Per-node, per-row fixed one-minute forwarding limit. It can be + instead require a real configured, flood-allowed region with that name.
    • +
    • region=<name>: Rewrite using an existing locally allowed region and one of + that region's transport keys.
    • +
    • rate=N/min: Per-node, per-row fixed one-minute forwarding limit. It can be the only action or accompany scope=/region=. Counters are charged only - for packets that pass all forwarding gates. -- retry, retry=on, retry=allow, or action=retry: Allow a matching + for packets that pass all forwarding gates.
    • +
    • retry, retry=on, retry=allow, or action=retry: Allow a matching received flood packet to enter the configured flood-retry sequence. With no active retry rows, retry eligibility remains backward compatible and is controlled by the global retry settings. Once any active retry row exists, the matching rows become a retry allow-list: a received flood must match at least one surviving retry row. flood.retry.bridge still selects ordinary or bridge-bucket completion for the allowed packet. This action can accompany - rewrite, rate, or stop, but not drop; compact syntax uses f=r. -- priority=0-255: Optional primary processing order. Higher values run first. + rewrite, rate, or stop, but not drop; compact syntax uses f=r.
    • +
    • priority=0-255: Optional primary processing order. Higher values run first. At the same numeric priority, authenticated channel matches run before raw hash:XX matches, which run before channel=*; lower slot number breaks the remaining tie. The default is 0; pri= is an alias. An explicitly higher - numeric priority still overrides this automatic specificity ordering. -- stop or action=stop: Apply this matching row, then stop lower-order FPF7 + numeric priority still overrides this automatic specificity ordering.
    • +
    • stop or action=stop: Apply this matching row, then stop lower-order FPF7 rows from processing. It can stand alone or accompany drop, rewrite, or rate. A stop-only row acts as an exception to lower-priority FPF7 rules. If the same row uses region= and that configured region is missing, denied, wildcard, or has no usable transport key, both the rewrite and its stop are inert so lower-order safety rows still run. A direct scope= target does - not depend on region configuration. -- suspend=tempradio: Optional. Skip this row only while the temporary radio - is actually active. -- require=region: Legacy alias for in=allowed. Apply the row only if the + not depend on region configuration.
    • +
    • suspend=tempradio: Optional. Skip this row while either tempradio or + tempradio2 is active, including scheduled temporary sessions.
    • +
    • require=region: Legacy alias for in=allowed. Apply the row only if the original incoming packet already passes this repeater's region gate. An incoming transport scope must resolve to a locally allowed region; an unscoped flood must be allowed by the wildcard region. The check - occurs before any scope rewrite during this receive pass. -- tx=slow: Optional and valid with scope= or region=. Use an effective inbound + occurs before any scope rewrite during this receive pass.
    • +
    • tx=slow: Optional and valid with scope= or region=. Use an effective inbound rxdelay base of max(2, configured rxdelay * 2), keep normal outbound queue priority, and retransmit with the maximum supported txdelay factor of 2.0. Scope rows default to fast; tx=fast explicitly restores that - default when replacing a slow row. -- path=blacklist: Optional unordered path condition. The persistent blacklist + default when replacing a slow row.
    • +
    • path=blacklist: Optional unordered path condition. The persistent blacklist is repeater-only. It contains up to 255 unique 3-byte repeater IDs on ESP32 builds and 18 on other builds, each written as six hexadecimal digits. A packet with 3-byte path hashes matches after one exact ID hit. A packet with 2-byte path hashes matches after two path entries match the first two bytes of listed IDs. Packets with 1-byte path hashes never match this condition. - Each received path entry is counted at most once.

      + Each received path entry is counted at most once.
    • +

    The payload names follow the MeshCore packet-format allocation:

    @@ -9623,13 +9785,16 @@ compile this table.

    -

    Route scope: Rules are evaluated only for the two flood route values: +

    Route scope: mode=radio rules are evaluated only for the two flood route values: ROUTE_TYPE_TRANSPORT_FLOOD (0x00, flood plus transport codes) and ROUTE_TYPE_FLOOD (0x01, unscoped flood). Direct routes 0x02 and 0x03 -are never affected.

    -

    Behavior: Match fields within one row are ANDed. Every FPF7 row is matched +are unaffected by radio rules. Bridge/cross rules also cover direct routes at +their respective transport boundaries.

    +

    Behavior: Match fields within one row are ANDed. Radio rows are matched against the same immutable receive-time packet, before any rule changes its -scope. Matching rows are processed in descending priority. At equal numeric +scope. Bridge/cross rows match the packet at their admission boundary; a TX +packet can already have an appended hop or rewritten scope. Each mode evaluates +only its applicable rows, processed in descending priority. At equal numeric priority, authenticated channel matches precede raw hashes, which precede an unrestricted channel matcher; lower slot wins after that. The first matching stop row is included and all lower-order FPF7 matches are discarded. A stop @@ -9674,10 +9839,11 @@ region names rather than transient numeric region IDs. Removing, reordering, or reusing a region ID therefore cannot silently retarget a rule. If a saved input or target region name is absent, that input match or rewrite is inert; restoring the same region name reactivates it. -While the temporary radio is active, only rows explicitly marked -suspend=tempradio are skipped. tempradio is a radio state, not an OTA mode; -normal payload types can also use the temporary channel. Other rows remain in -force. A malformed persisted table fails open (no general rules are applied).

    +While either tempradio or tempradio2 is active, only rows explicitly marked +suspend=tempradio are skipped. Temporary radio is a radio state, not an OTA +mode; normal payload types can also use the temporary channel. Other rows +remain in force, and suspended rows resume after both temporary sessions end. +A malformed persisted table fails open (no general rules are applied).

    Within one receive evaluation, rows that use the same channel key share one authentication result. The cache is discarded after that packet and stores neither plaintext nor passwords; different keys are authenticated separately. @@ -9712,10 +9878,10 @@ can deliberately reverse this order by assigning the hash row a higher numeric

    Deleting or replacing the last active retry row restores the legacy global retry eligibility. Firmware that predates the retry/hash:XX FPF7 extension cannot preserve tables containing those rows; remove them before downgrading.

    -

    Default row: Repeater firmware and FULL ESP32 room-server firmware seed a +

    Default rows: Repeater firmware and FULL ESP32 room-server firmware seed a new flood-filter table with ota all suspend=tempradio in slot 1. This blocks repeated LoRa OTA (0x0C) -floods at every received hop unless temporary radio is actually active. The OTA +floods at every received hop unless either temporary radio profile is active. The OTA core independently refuses OTA receive, relay, and transmit outside temporary radio. The row is editable and deletable; once the table is saved, deletion is persistent. Restore the exact seeded row with:

    @@ -9723,6 +9889,14 @@ persistent. Restore the exact seeded row with:

    Omitting all is equivalent. Omit .1 as well to reuse an identical rule or the first empty slot instead of replacing slot 1.

    +

    Generalized repeaters also seed slot 2 with the authenticated #wardriving +radio hop limit and slot 3 with the bridge/crossover block:

    +
    set flood.rule.2 type=any channel=#wardriving hops=5+ drop
    +set flood.rule.3 type=any channel=#wardriving hops=all mode=bridge,cross drop
    +
    +

    These numbered commands replace those slots. Saved tables are preserved on +upgrade; use the unnumbered third command to add the new rule without replacing +an occupied slot. See restoring the three defaults.

    Remote-admin lockout warning: There are no hidden payload-type or short-hop exceptions. FPF7 drop and rate rows may block req, response, txt_msg, anon_req, path, ACK, and multipart traffic beginning at hop 0 when their @@ -9735,14 +9909,82 @@ or action. get flood.filter or get flood.rule gives a compact list. Use the numbered form for full details, including channel, prefix, original-scope condition, action, timing, rate, and temporary-radio suspension.

    -

    If all of those fields plus long names would exceed one CLI reply, the -numbered form automatically switches to a non-truncating compact spelling. -The compact aliases are also accepted by set: c= means channel=, p= -means prefix=, i=*|n|s|a|u|s:<scope>|r:<region> means the corresponding -in= condition, q=N means rate=N/min, pri=N means priority, and f=str -combines slow timing (s), temporary-radio suspension (t), and retry -allowance (r). Packet type is shown numerically -in that fallback. Normal-sized rows keep the descriptive spelling above.

    +

    fr is a shorter alias for flood.rule, with the same explicit-action +requirement. Short and long field names can be mixed in either command:

    +
    set flood.rule.3 type=any channel=#wardriving hops=all mode=bridge,cross drop
    +set fr.3 any c=#wardriving m=bc d
    +get fr.3
    +
    +

    The two setters above save the same row. get fr.3 returns the complete +short setter; get fr lists the table. Unnumbered set fr ... reuses an +identical row or adds one to the first empty slot. del fr.N and del fr all +have the same behavior as their long forms.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Full tokenShort token
    type=...Positional type or t=...; * means any
    hops=...Positional range or h=...; * means all
    mode=radio/bridge/cross/bridge,crossm=r/b/c/bc (choose one value)
    channel=..., prefix=...c=..., p=...
    path=blacklistp=bl (repeater only)
    in=any/none/scoped/allowed/unknowni=*/n/s/a/u (choose one value)
    in=scope:name, in=region:namei=s:name, i=r:name
    drop, stop, retryd, s, r
    scope=name, region=names=name, r=name
    rate=N/min, priority=Nq=N, pri=N
    tx=slow, suspend=tempradio, retryf=s, f=t, f=r; combine as f=str
    +

    All existing validation and permissions apply. m=cb, m=b,c, and m=c,b +also mean bridge and crossover. Short aliases for flood.channel.scope, +flood.moderation, and blacklist management are not added.

    +

    The numbered long getters use this complete short setter when descriptive +fields would exceed a reply. Defaults are omitted and specific payload types +are printed numerically. If it still cannot fit, the reply is +Err - compact command exceeds reply size, never a partial setter. +Private channel keys are shown as key:XXXXXXXX; that reference can be +reused while an active rule on the same device holds the key. Copying it to +another device requires the original key, unless that device already has a +matching rule. Unknown or ambiguous references are rejected. See the +shorthand guide for examples.

    On generalized repeaters, filter rows, scope-rewrite rows, the shared blacklist, and flood.channel.data compatibility state are committed in one atomic FPF7 image. Compact FPF6 profiles retain separate files. Replacing or deleting @@ -9867,7 +10109,7 @@ del flood.moderation.3

    Filter manager scope: Permission 5 can use an explicit allowlist of non-secret operational/filter status commands and can change the forwarding controls repeat, loop.detect, flood.max*, flood.channel.data*, -flood.filter*, flood.rule*, and +flood.filter*, flood.rule*, fr[.N], and flood.moderation*. It cannot read guest, WiFi, MQTT, bridge, or other credentials, and it cannot change regions, ACL entries, radio settings, or other admin configuration. Permission 4 diff --git a/espnow_bridge_setup/index.html b/espnow_bridge_setup/index.html index a2c5d67d..42401cb4 100644 --- a/espnow_bridge_setup/index.html +++ b/espnow_bridge_setup/index.html @@ -857,6 +857,17 @@ +

  • + +
  • + + + + Keep wardriving traffic off the bridge + + + +
  • @@ -2893,6 +2904,17 @@ + + +
  • + + + + Keep wardriving traffic off the bridge + + + +
  • @@ -3078,6 +3100,23 @@ delivery.

    For every command's full details, see the bridge CLI reference.

    For a broader comparison with a Linux-based bridge, see the MeshCore Nexus bridging guide.

    +

    Keep wardriving traffic off the bridge

    +

    New generalized repeater filter tables include a third built-in rule that +blocks authenticated #wardriving text and data in both bridge directions, +at every hop count. The same row blocks crossover between radio profiles:

    +
    get flood.rule.3
    +set flood.rule type=any channel=#wardriving hops=all mode=bridge,cross drop
    +
    +

    The same rule can be added with the shorter command:

    +
    set fr any c=#wardriving m=bc d
    +
    +

    Both forms use the same table. m=b means bridge only, m=c means crossover +only, and get fr.N returns a short command for copying a numbered rule.

    +

    The unnumbered command adds the rule safely on existing devices whose saved +tables predate this default. It works with either bridge packet source and +both ESP-NOW formats. Nearby same-profile LoRa forwarding retains the separate +four-hop default. Use mode=bridge for a bridge-only block, or mode=cross for +a crossover-only block. See the mode matrix and examples.

    diff --git a/filter_tool/index.html b/filter_tool/index.html index e71f2206..f6f2ce27 100644 --- a/filter_tool/index.html +++ b/filter_tool/index.html @@ -2910,7 +2910,7 @@ drafts are not uploaded anywhere.

    The phases and core conditions model current FPF7 behavior, including its forward rows, scope rewrites, and shared blacklist. The readable policy language, JSON, and Base64 bundle are still a prototype: current firmware - is configured with set flood.* commands and cannot install a + is configured with set flood.* or set fr commands and cannot install a bundle from this page.

    @@ -3006,8 +3006,8 @@ in the simulator below. The examples draw from when type=any hops=all path=blacklist do drop +

    The factory example contains all three repeater defaults. + The playground's via= traffic-path matcher corresponds to firmware + mode=radio|bridge|cross|bridge,cross; the advanced Active/Shadow/Disabled + mode is a separate playground setting. See the + firmware mode guide. + This simulator models flood packets; firmware bridge/cross rules also cover direct routes.

    Common match settings

    + +