Skip to content

luci-app-netmode: add app for modem network mode switching#8690

Open
devopnem wants to merge 1 commit into
openwrt:masterfrom
devopnem:feat/luci-app-netmode
Open

luci-app-netmode: add app for modem network mode switching#8690
devopnem wants to merge 1 commit into
openwrt:masterfrom
devopnem:feat/luci-app-netmode

Conversation

@devopnem

@devopnem devopnem commented Jun 7, 2026

Copy link
Copy Markdown

Features:

  • Auto-detection of modem AT port
  • Display current operator and network mode
  • Switch between Auto, 4G LTE Only, and 3G Only modes
  • Non-blocking UI with button state management
  • Current-mode button is automatically disabled
  • Collapsible Advanced Settings panel for port selection
  • Dark-mode friendly (uses theme CSS variables)
  • Uses comgt for safe AT command communication with timeout

Pull request details

Description

Add a LuCI JavaScript application that allows users to view and switch modem network access technology via AT commands.

Screenshot or video of changes (if applicable)

image

Tested on

OpenWrt version: OpenWrt 25.12.4 (r32933-4ccb782af7)
LuCI version: openwrt-25.12 branch (26.155.67407~06be235)
Web browser(s): LibreWolf 151.0.1-2

Checklist

  • This PR is not from my main or master branch 💩, but a separate branch. ✅
  • Each commit has a valid ✒️ Signed-off-by: <my@email.address> row (via git commit --signoff).
  • Each commit and PR title has a valid 📝 <package name>: title first line subject for packages.
  • Incremented 🆙 any PKG_VERSION in the Makefile.
  • (Optional) Includes what Issue it closes (e.g. openwrt/luci#issue-number).
  • (Optional) Includes what it depends on (e.g. openwrt/packages#pr-number in sister repo).

@github-actions

This comment has been minimized.

@devopnem devopnem force-pushed the feat/luci-app-netmode branch from 1f935ee to d8c6b5c Compare June 7, 2026 04:58

@openwrt-ai openwrt-ai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the new luci-app-netmode app. Main concern is an ACL gap that breaks port auto-detection at runtime, plus an input-validation issue in at.sh. Details inline.


Generated by Claude Code

"file": {
"/usr/share/netmode/at.sh": ["exec"]
}
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This ACL grants only file exec on at.sh, but load() in netmode.js calls fs.list('/dev') to auto-detect ports. The file.list ubus method requires a "list" permission on the target path (rpcd file.c L548), which is missing here. For a session that only holds this ACL group, the /dev listing is denied; the JS swallows it via .catch(() => []), so _ports stays empty, _device is null, and both auto-detection and the Advanced port selector silently break ("No modem ports found").

Either add a list grant for /dev, e.g.:

Suggested change
}
"file": {
"/usr/share/netmode/at.sh": ["exec"],
"/dev": ["list"]
}

or follow luci-app-p910nd, which avoids fs.list and instead execs find against a specific command-line ACL.


Generated by Claude Code

TMPSCRIPT=$(mktemp /tmp/netmode.XXXXXX)

printf 'opengt\nset com 115200n81\nset senddelay 0.05\nsend "%s^m"\nwaitfor 8 "OK","ERROR","+COPS:"\nget 1 "^m" $s\nprint $s\n' "$CMD" > "$TMPSCRIPT"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$CMD ($*) is interpolated unvalidated into the comgt send "%s^m" string. A " in the argument terminates the comgt string literal and lets the caller inject additional comgt directives; any AT string is also passed straight to the modem. Because the ACL grants blanket exec on this path (no per-command-line match), the per-cmdline check in rpcd is bypassed and any session holding this ACL can invoke at.sh with arbitrary arguments (rpcd file.c L937). Consider validating $CMD against an allowlist (the script only ever needs AT+COPS? and AT+COPS=0[,,,N]) rather than forwarding arbitrary AT commands.


Generated by Claude Code

function actShort(act) {
if (act === 7) return '4g';
if (act === 2) return '3g';
return 'auto';

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this only treats act 7 as 4G and act 2 as 3G; the other 3G technologies in actLabels (4 HSDPA, 5 HSUPA, 8 HSPA+) and the LTE/5G values (9 LTE-A, 10 NR) all fall through to 'auto'. So when the modem reports, e.g., HSPA+, the "3G Only" button is not marked active even though the modem is on 3G. Consider mapping all UTRAN-family ACTs to '3g' and all E-UTRAN/NR ACTs to '4g'.


Generated by Claude Code

@devopnem devopnem force-pushed the feat/luci-app-netmode branch from d8c6b5c to 836f96e Compare June 7, 2026 05:56

@openwrt-ai openwrt-ai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed at head 836f96e. The earlier ACL /dev listing gap, the at.sh arbitrary-AT-command concern, and the actShort 3G/4G mapping were all addressed in this push. One new issue from the added at.sh allowlist is inline.


Generated by Claude Code

CMD="$*"

case "$CMD" in
at+cops\?|at+cops=0|at+cops=0,,,2|at+cops=0,,,7)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The allowlist patterns are lowercase, but the frontend sends the AT commands in uppercase: AT+COPS? / AT+COPS=0 / AT+COPS=0,,,7 / AT+COPS=0,,,2.POSIXcasein/bin/sh(ash) is case-sensitive, so every command the app sends falls through to the*)branch and returnsERROR: command not allowed` (exit 1). As written the status query and all three switch buttons are non-functional. Match the uppercase forms the frontend actually sends:

Suggested change
at+cops\?|at+cops=0|at+cops=0,,,2|at+cops=0,,,7)
AT+COPS\?|AT+COPS=0|AT+COPS=0,,,2|AT+COPS=0,,,7)

Generated by Claude Code

Add a LuCI JavaScript application that allows users to view and switch
modem network access technology via AT commands.

Features:
- Auto-detection of modem AT port
- Display current operator and network mode
- Switch between Auto, 4G LTE Only, and 3G Only modes
- Non-blocking UI with button state management
- Current-mode button is automatically disabled
- Collapsible Advanced Settings panel for port selection
- Dark-mode friendly (uses theme CSS variables)
- Uses comgt for safe AT command communication with timeout

Signed-off-by: Devon Openheim <devopenm@proton.me>
@devopnem devopnem force-pushed the feat/luci-app-netmode branch from 836f96e to d3d8cee Compare June 8, 2026 07:31

@openwrt-ai openwrt-ai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed at head d3d8cee. The only change since my last review (836f96e) is the at.sh allowlist case patterns switching from lowercase to uppercase (AT+COPS\?|AT+COPS=0|AT+COPS=0,,,2|AT+COPS=0,,,7). These now match the four uppercase commands the frontend sends, so the earlier case-sensitivity breakage is resolved. No new issues found.


Generated by Claude Code

@devopnem devopnem force-pushed the feat/luci-app-netmode branch from 9d58aef to d3d8cee Compare June 17, 2026 09:09
@github-actions

This comment has been minimized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants