update 2025-02-13 20:42:01

This commit is contained in:
actions-user 2025-02-13 20:42:01 +08:00
parent d9e7dca2a2
commit 8e6cc55574
8 changed files with 356 additions and 0 deletions

View File

@ -0,0 +1,17 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.0.5-20241208
PKG_RELEASE:=
PKG_MAINTAINER:=jjm2473 <jjm2473@gmail.com>
LUCI_TITLE:=Easy Access AP / Modem
LUCI_PKGARCH:=all
define Package/luci-app-ap-modem/conffiles
/etc/config/ap_modem
endef
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature

View File

@ -0,0 +1,54 @@
'use strict';
'require view';
'require uci';
'require form';
return view.extend({
load: function() {
return Promise.all([
uci.load('ap_modem')
]);
},
render: function() {
var m, s, o, ss;
m = new form.Map('ap_modem', _('Access AP / Modem'),
_('Allows clients in the local network to access AP or modem on different subnet.'));
s = m.section(form.NamedSection, 'config', 'ap_modem', _('Global Settings'));
s.anonymous = true;
s.addremove = false;
o = s.option(form.Flag, 'enabled', _('Enable'));
o.rmempty = false;
s = m.section(form.NamedSection, 'config', 'ap_modem', _('Interface Settings'));
s.anonymous = true;
s.addremove = false;
[
{id:"lan", title:_("LAN"), subtitle:_("AP on LAN side"), placeholder:"192.168.31.254",
example:_("<br>For example, you want to access the AP, its IP address is 192.168.31.1, but the client and the router are not in its subnet, so it cannot be connected. "
+ "Then you can add 192.168.31.254 here, the client will be able to access 192.168.31.1 after saving and applying.")},
{id:"wan", title:_("WAN"), subtitle:_("AP / Modem on WAN side"), placeholder:"192.168.1.254",
example:_("<br>For example, you want to access the modem, its IP address is 192.168.1.1, but because it uses PPPoE bridge mode, so it cannot be connected. "
+ "Then you can add 192.168.1.254 here, the client will be able to access 192.168.1.1 after saving and applying.")},
].forEach(function(vif) {
s.tab(vif.id, vif.title);
o = s.taboption(vif.id, form.SectionValue, '__'+vif.id+'__', form.NamedSection, vif.id, null,
vif.subtitle, _('Here add the IP address of the same subnet as the target device, but not the same as the target device. <br>Do not add IPs already used by other devices.') + vif.example);
ss = o.subsection;
ss.anonymous = true;
o = ss.option(form.DynamicList, 'ipaddr', _('Virtual IP'), _('Supports "IP/MASK", "IP/PREFIX", and pure "IP" format, pure "IP" assumes a prefix of 24 bits'));
o.datatype = 'ipmask4';
o.placeholder = vif.placeholder;
});
return m.render();
}
});

View File

@ -0,0 +1,43 @@
msgid ""
msgstr ""
"Content-Type: text/plain; charset=UTF-8"
msgid "Access AP / Modem"
msgstr "访问AP/光猫"
msgid "Allows clients in the local network to access AP or modem on different subnet."
msgstr "让局域网客户端访问不同子网的AP或光猫"
msgid "Global Settings"
msgstr "全局设置"
msgid "Interface Settings"
msgstr "网络接口配置"
msgid "AP on LAN side"
msgstr "位于LAN口的AP"
msgid "AP / Modem on WAN side"
msgstr "位于WAN口的AP或光猫"
msgid "Virtual IP"
msgstr "虚拟IP地址"
msgid ""
"Here add the IP address of the same subnet as the target device, but not the same as the target device. "
"<br>Do not add IPs already used by other devices."
msgstr ""
"这里添加与目标设备同子网的IP地址但不能与目标设备IP完全相同。<br>不要添加其他设备正在使用的IP。"
msgid ""
"<br>For example, you want to access the AP, its IP address is 192.168.31.1, but the client and the router are not in its subnet, so it cannot be connected. "
"Then you can add 192.168.31.254 here, the client will be able to access 192.168.31.1 after saving and applying."
msgstr "<br>例如你想要访问AP后台它的IP地址是192.168.31.1但是由于现在客户端和路由器都不在它的子网无法连接。那么可以在这里添加192.168.31.254保存并应用之后客户端就能访问192.168.31.1了。"
msgid ""
"<br>For example, you want to access the modem, its IP address is 192.168.1.1, but because it uses PPPoE bridge mode, so it cannot be connected. "
"Then you can add 192.168.1.254 here, the client will be able to access 192.168.1.1 after saving and applying."
msgstr "<br>例如你想要访问光猫后台它的IP地址是192.168.1.1但是由于它使用PPPoE桥接模式无法连接。那么可以在这里添加192.168.1.254保存并应用之后客户端就能访问192.168.1.1了。"
msgid "Supports \"IP/MASK\", \"IP/PREFIX\", and pure \"IP\" format, pure \"IP\" assumes a prefix of 24 bits"
msgstr "支持“IP/掩码”、“IP/前缀长度”、以及纯“IP”格式纯“IP”则假设前缀24位"

View File

@ -0,0 +1 @@
zh-cn

View File

@ -0,0 +1,8 @@
config ap_modem 'config'
option enabled '0'
config interface 'lan'
# list ipaddr '192.168.31.254'
config interface 'wan'
# list ipaddr '192.168.1.254'

View File

@ -0,0 +1,208 @@
#!/bin/sh /etc/rc.common
START=20
USE_PROCD=1
boot() {
# procd will call service_triggers
rc_procd true
}
service_triggers() {
procd_add_reload_trigger "network" "ap_modem"
}
find_uci_section_i() {
local key="$2"
local value="$3"
local testv
config_get testv "$1" "$key"
[[ "$value" = "$testv" ]] && echo "$1"
}
find_uci_section() {
local config="$1"
local type="$2"
local key="$3"
local value="$4"
(
config_load "$config"
config_foreach find_uci_section_i "$type" "$key" "$value"
)
}
generate_config() {
[[ "`uci -q get network.lan.device`" = "br-lan" ]] || {
echo "network.lan.device != br-lan in uci" >&2
return 1
}
local wan_dev="`uci -q get network.wan.device`"
[[ -z "$wan_dev" ]] && {
echo "get network.wan.device in uci failed" >&2
return 1
}
local lan_dev=`find_uci_section network device name 'br-lan' | head -1`
[[ -z "$lan_dev" ]] && {
echo "network.device.name=br-lan not found in uci" >&2
return 1
}
local wan_zone=`find_uci_section firewall zone name 'wan' | head -1`
[[ -z "$wan_zone" ]] && {
echo "firewall.zone.name=wan not found in uci" >&2
return 1
}
# virutal lan device
uci -q get network.veth_lan >/dev/null || uci -q batch <<-EOF >/dev/null
set network.veth_lan=device
set network.veth_lan.type=veth
set network.veth_lan.name=vap-lan
set network.veth_lan.sendredirects=0
set network.veth_lan.ipv6=0
set network.veth_lan.multicast=0
set network.veth_lan.peer_name=vap-lan-peer
EOF
uci -q get network.veth_lan_peer >/dev/null || uci -q batch <<-EOF >/dev/null
set network.veth_lan_peer=device
set network.veth_lan_peer.name=vap-lan-peer
set network.veth_lan_peer.sendredirects=0
set network.veth_lan_peer.ipv6=0
set network.veth_lan_peer.multicast=0
EOF
uci -q get "network.$lan_dev.ports" | grep -Fwq 'vap-lan' || uci add_list "network.$lan_dev.ports=vap-lan"
# interface
if uci -q get network.vap_lan >/dev/null; then
uci -q delete network.vap_lan.auto
else
uci -q batch <<-EOF >/dev/null
set network.vap_lan=interface
set network.vap_lan.proto=static
set network.vap_lan.device=vap-lan-peer
set network.vap_lan.defaultroute=0
set network.vap_lan.delegate=0
EOF
fi
if uci -q get network.vap_wan >/dev/null; then
uci -q delete network.vap_wan.auto
else
uci -q batch <<-EOF >/dev/null
set network.vap_wan=interface
set network.vap_wan.proto=static
set network.vap_wan.device=$wan_dev
set network.vap_wan.defaultroute=0
set network.vap_wan.delegate=0
EOF
fi
# firewall
local fw_wan_net="`uci -q get firewall.$wan_zone.network`"
echo "$fw_wan_net" | grep -Fwq 'vap_lan' || uci -q batch <<-EOF >/dev/null
add_list firewall.$wan_zone.network=vap_lan
EOF
echo "$fw_wan_net" | grep -Fwq 'vap_wan' || uci -q batch <<-EOF >/dev/null
add_list firewall.$wan_zone.network=vap_wan
EOF
uci commit firewall
# ip
local bip
local black_ip="127.0.0.1/8"
[[ "`uci -q get network.lan.proto`" = "static" ]] && {
local lan_ip="`uci -q get network.lan.ipaddr`"
if [[ -n "$lan_ip" ]]; then
local netmask="`uci -q get network.lan.netmask`"
[[ -n "$netmask" ]] || netmask=255.255.255.255
for bip in $lan_ip; do
if [[ "$bip" = "*/*" ]]; then
eval "$(ipcalc.sh $bip )";black_ip="$black_ip $IP/$PREFIX"
else
eval "$(ipcalc.sh $bip $netmask )";black_ip="$black_ip $IP/$PREFIX"
fi
done
fi
}
logger -t 'ap_modem' -p INFO "black: $black_ip"
local ipaddr
local vip
local vip_p
local vnet
local bnet
local ok
local vif
for vif in lan wan; do
config_get ipaddr $vif ipaddr
[[ -n "$ipaddr" ]] || continue
for vip in $ipaddr; do
ok=1
[[ "$vip" = "*/*" ]] || vip="$vip/24"
eval "$(ipcalc.sh $vip )";vip="$IP";vip_p="$PREFIX"
[[ "$vip_p" = 32 ]] && {
logger -t 'ap_modem' -p DEBUG "vap_$vif skip $vip/$vip_p"
break
}
for bip in $black_ip; do
eval "$(ipcalc.sh "$bip" )";bip="$IP";
[[ "$PREFIX" -le "$vip_p" ]] || PREFIX=$vip_p
eval "$(ipcalc.sh "$vip/$PREFIX" )";vnet="$NETWORK";
eval "$(ipcalc.sh "$bip/$PREFIX" )";bnet="$NETWORK";
if [[ "$vnet" = "$bnet" ]]; then
logger -t 'ap_modem' -p DEBUG "vap_$vif skip $vip/$vip_p"
ok=0
break
fi
done
[[ "$ok" = 1 ]] && {
uci add_list "network.vap_$vif.ipaddr=$vip/$vip_p"
black_ip="$black_ip $vip/$vip_p"
}
done
done
uci commit network
}
clean_config() {
local wan_zone=`find_uci_section firewall zone name 'wan' | head -1`
[[ -z "$wan_zone" ]] || uci -q batch <<-EOF >/dev/null
del_list firewall.$wan_zone.network=vap_lan
del_list firewall.$wan_zone.network=vap_wan
commit firewall
EOF
local lan_dev=`find_uci_section network device name 'br-lan' | head -1`
[[ -z "$lan_dev" ]] || {
uci del_list "network.$lan_dev.ports=vap-lan"
}
uci -q batch <<-EOF >/dev/null
set network.vap_lan.auto=0
set network.vap_wan.auto=0
delete network.veth_lan_peer
delete network.veth_lan
commit network
EOF
}
start_service() {
config_load ap_modem
config_get_bool enabled "config" enabled 0
uci -q batch <<-EOF >/dev/null
delete network.vap_lan.ipaddr
delete network.vap_wan.ipaddr
commit network
EOF
if [[ "$enabled" = "1" ]]; then
generate_config
else
clean_config
fi
/etc/init.d/network reload
return 0
}
stop_service() {
clean_config
/etc/init.d/network reload
}

View File

@ -0,0 +1,14 @@
{
"admin/network/ap_modem": {
"title": "Access AP / Modem",
"order": 99,
"action": {
"type": "view",
"path": "ap_modem"
},
"depends": {
"acl": [ "luci-app-ap-modem" ],
"uci": { "ap_modem": true }
}
}
}

View File

@ -0,0 +1,11 @@
{
"luci-app-ap-modem": {
"description": "Grant access to 'Access AP / Modem'",
"read": {
"uci": [ "ap_modem" ]
},
"write": {
"uci": [ "ap_modem" ]
}
}
}