NETMGR_DESIGN.md §7/§13 期4 落地(只动 patch_v2/meow_netmgrd/ + patch_v2/sdk/ 追加式): 1. SDK 自愿通道(§6.3/§4):meow_ui.h 新增 meow_net_policy_check(host)(0=放行 1=block; netmgrd 不在/超时→0 乐观放行)+ meow_net_report(rx,tx)(自愿上报,§4 字节级记账自报通道)。 meow_ipc.h 追加 0xEE MSG_NET_SDK(op=CHECK/REPORT)/ 0xEF RESULT。netmgrd 侧:CHECK 以 app_id→实体 app:<pkg> 评估 policy_net_blocked||dns_query_domain_denied;REPORT 记入 per-实体 g_ent_bytes(status JSON 新增 entity_bytes)。SDK 实现 meow_net_ipc.c(一次 connect+send+read, 降级不崩);meow_ui.a 重编。 2. wifi forget <id>:wpa_cli remove_network+save_config(MeowOS;HibyOS 只读门控),CLI+IPC 接通 (286 launcher 录入 UI 缺口)。 3. RSSI:wifi_status 在 status 无 signal= 时回退 wpa_cli signal_poll(真机 rssi=-38,修面板 rssi=null 缺口)。 4. DNS AAAA 过滤:global dns.filter_aaaa=0|1(默认 0 透传;纯 IPv4 设备可置 1 让 AAAA 查询回空答案回落 A)。 5. 静态 iptables 评估(devdocs/plan/NETMGR_IPTABLES_EVAL.md,本机不入库):iptables-legacy 1.8.9 交叉 编译成功(~578KB,含 owner/cgroup/REDIRECT 等全部 extension),但内核实测 matches 仅 quota/icmp/udp/tcp、targets 仅 NFQUEUE/NFLOG/ERROR、无 nat 表、全部进程 UID 0 → **per-app 管控 与 REDIRECT 透明代理判不可行**(与 NETWORK_HW_FACTS 一致);正路为 per-app UID 框架改造(单独立项)。 验证:宿主 test_netmgrd.sh 70/70 + qemu 70/70;test_netmgrd_p2/p3/p5 宿主全过 + 交叉 0 warning; netmgrd_authtest 全过;sdk meow_net_ipc 交叉 0 warning。真机(固件 netmgrd 共存,独立 socket+DNS off): wifi status rssi=-38(signal_poll)、wifi forget 0(DISABLED 安全移除,id1 CURRENT 保留、wifi 未断)、 SDK policy check(CHECK_GOOD=0/CHECK_BLOCK=1/REPORT ok)、policy show 正常;resolv.conf 未触碰、 固件 meow_netmgrd(pid) running 未动;测试产物全清。 新 md5:meow_netmgrd 20243ea1a800b29badefebb395603aaf;meow_ui.a be24214e24faadba63577f3a98c2c9d1 (主会话更 fw_content.conf / 热更设备 / 记录新 meow_ui.a)。
367 lines
17 KiB
Bash
Executable File
367 lines
17 KiB
Bash
Executable File
#!/bin/bash
|
||
# test_netmgrd.sh — meow_netmgrd 宿主桩测试(假 sysfs/procfs 节点 + 桩后端命令,MEOW_* env 覆盖)。
|
||
# 用法:./test_netmgrd.sh [host二进制路径](默认 ./meow_netmgrd_host;可传 mipsel 二进制 + QEMU 前缀)
|
||
# QEMU="qemu-mipsel" ./test_netmgrd.sh ./meow_netmgrd # qemu 验证
|
||
set -u
|
||
cd "$(dirname "$0")"
|
||
BIN="${1:-./meow_netmgrd_host}"
|
||
Q="${QEMU:-}"
|
||
T=$(mktemp -d /tmp/netmgrdtest.XXXXXX)
|
||
trap 'kill $DPID 2>/dev/null; rm -rf "$T"' EXIT
|
||
PASS=0; FAIL=0
|
||
ck() { # ck <名> <期望子串> <实际>
|
||
if echo "$3" | grep -qF "$2"; then PASS=$((PASS+1)); echo "PASS $1";
|
||
else FAIL=$((FAIL+1)); echo "FAIL $1: 期望含 [$2] 实际=[$3]"; fi
|
||
}
|
||
|
||
# ---- 搭假节点 ----
|
||
NET="$T/net"; RF="$T/rfkill"; BT="$T/bt"
|
||
mkdir -p "$NET/lo" "$NET/wlan0" "$RF/rfkill0" "$RF/rfkill1" "$BT/hci0"
|
||
echo up > "$NET/lo/operstate"
|
||
echo up > "$NET/wlan0/operstate"
|
||
echo wlan > "$RF/rfkill0/type"; echo 0 > "$RF/rfkill0/soft"; echo 0 > "$RF/rfkill0/hard"
|
||
echo bluetooth > "$RF/rfkill1/type"; echo 1 > "$RF/rfkill1/soft"; echo 0 > "$RF/rfkill1/hard"
|
||
echo 00:1A:7D:DA:71:13 > "$BT/hci0/address"
|
||
echo on > "$BT/hci0/power"
|
||
cat > "$T/netdev" <<'EOF'
|
||
Inter-| Receive | Transmit
|
||
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
|
||
lo: 1000 10 0 0 0 0 0 0 1000 10 0 0 0 0 0 0
|
||
wlan0: 5000000 5000 0 0 0 0 0 0 1000000 1000 0 0 0 0 0 0
|
||
EOF
|
||
cat > "$T/route" <<'EOF'
|
||
Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
|
||
wlan0 005EC20A 6F3DC20A 0003 0 0 0 00FFFFFF 0 0 0
|
||
lo 0100007F 00000000 0001 0 0 0 000000FF 0 0 0
|
||
EOF
|
||
printf 'nameserver 223.5.5.5\nnameserver 10.78.193.1\n' > "$T/resolv"
|
||
echo meow > "$T/boot_mode"
|
||
|
||
# ---- 期2 观测层打桩:/proc/net/{tcp,udp}(IPv4 LE hex)+ 域名规则 conf + amsd/svcd 缺省 ----
|
||
cat > "$T/tcp" <<'EOF'
|
||
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
|
||
0: 32C14E0A:5137 0905CD8C:01BB 01 00000000:00000000 00:00000000 00000000 1000 0 12345 1 0 0 10 0
|
||
1: 32C14E0A:4F32 32C34E0A:01BB 01 00000000:00000000 00:00000000 00000000 1000 0 12346 1 0 0 10 0
|
||
2: 32C14E0A:0A00 00000000:0000 07 00000000:00000000 00:00000000 00000000 1000 0 67890 1 0 0 10 0
|
||
3: 32C14E0A:4F33 32C34E0A:01BB 01 00000000:00000000 00:00000000 00000000 1000 0 0 1 0 0 10 0
|
||
EOF
|
||
cat > "$T/udp" <<'EOF'
|
||
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
|
||
0: 0100007F:D301 0100007F:0035 07 00000000:00000000 00:00000000 00000000 0 0 99999 1 0 0 10 0
|
||
EOF
|
||
printf 'app:dev.player.ncm domain=-ads.example.com\nproc:dropbear domain=+x\n' > "$T/policy"
|
||
|
||
# 桩后端命令(popen stubbing)
|
||
cat > "$T/wpa_cli" <<'EOF'
|
||
#!/bin/sh
|
||
case "$1" in
|
||
status) echo "wpa_state=COMPLETED"; echo "ssid=MyWiFi"; echo "ip_address=10.78.193.50"; echo "signal=-45";;
|
||
scan) echo OK;;
|
||
scan_results) printf 'bssid / frequency / signal level / flags / ssid\nxx:xx / 2412 / -50 / WPA2 / TestAP\n';;
|
||
list_networks) printf 'network id / ssid / bssid / flags\n0\tMyWiFi\tany\t[CURRENT]\n';;
|
||
add_network) echo 1;;
|
||
set_network) echo OK;;
|
||
enable_network) echo OK;;
|
||
select_network) echo OK;;
|
||
disconnect) echo OK;;
|
||
esac
|
||
exit 0
|
||
EOF
|
||
cat > "$T/hciconfig" <<'EOF'
|
||
#!/bin/sh
|
||
echo "hci0: Type: Primary Bus: USB"
|
||
echo " BD Address: 00:1A:7D:DA:71:13 ACL MTU: 1021:8 SCO MTU: 64:1"
|
||
echo " UP RUNNING PSCAN"
|
||
EOF
|
||
cat > "$T/bluetoothctl" <<'EOF'
|
||
#!/bin/sh
|
||
echo "Device 00:1A:7D:DA:71:13 My Headset"
|
||
echo "Device 11:22:33:44:55:66 Speaker"
|
||
EOF
|
||
cat > "$T/ip" <<'EOF'
|
||
#!/bin/sh
|
||
for a in "$@"; do
|
||
if [ "$a" = "wlan0" ]; then echo "2: wlan0 inet 10.78.193.50/24 brd 255.255.255.255 scope global wlan0"; fi
|
||
if [ "$a" = "lo" ]; then echo "1: lo inet 127.0.0.1/8 scope host lo"; fi
|
||
done
|
||
exit 0
|
||
EOF
|
||
for f in wpa_cli hciconfig bluetoothctl ip; do chmod +x "$T/$f"; done
|
||
|
||
mkdir -p "$T/logs" "$T/pid"
|
||
# 期2:DNS 禁用(宿主无 root 不绑 53),观测层经 MEOW_TCP/UDP 打桩;amsd/svcd 缺省(实体归因走 proc:comm→unknown)。
|
||
ENVS="MEOW_NET_DIR=$NET MEOW_NETDEV=$T/netdev MEOW_NET_ROUTE=$T/route MEOW_RESOLV=$T/resolv
|
||
MEOW_RFKILL_DIR=$RF MEOW_BT_DIR=$BT MEOW_BOOT_MODE=$T/boot_mode MEOW_BOOTTS_CACHE=$T/bootts
|
||
MEOW_IP=$T/ip MEOW_WPA_CLI=$T/wpa_cli MEOW_HCICONFIG=$T/hciconfig MEOW_BLUETOOTHCTL=$T/bluetoothctl
|
||
MEOW_NET_SOCK=$T/net.sock MEOW_NET_POLL_SEC=1 MEOW_LOG_DIR=$T/logs
|
||
MEOW_TCP=$T/tcp MEOW_UDP=$T/udp MEOW_NET_POLICY=$T/policy
|
||
MEOW_AMS_SOCK=$T/no_ams MEOW_SVCD_SOCK=$T/no_svcd MEOW_DNS_DISABLE=1"
|
||
ln -sf "$(readlink -f "$BIN")" "$T/meow_net" # argv[0] 双形态 → CLI
|
||
|
||
# ---- T0: 守护起 ----
|
||
env $ENVS $Q "$BIN" --sock "$T/net.sock" >"$T/daemon.log" 2>&1 &
|
||
DPID=$!
|
||
for i in $(seq 1 30); do [ -S "$T/net.sock" ] && break; sleep 0.2; done
|
||
[ -S "$T/net.sock" ] || { echo "FAIL T0: daemon socket 未出现"; cat "$T/daemon.log"; exit 1; }
|
||
PASS=$((PASS+1)); echo "PASS T0 daemon up"
|
||
|
||
# ---- T1: status(读级,任意调用者)----
|
||
OUT=$(env $ENVS $Q "$T/meow_net" status 2>&1)
|
||
ck T1a "mode=meow src=daemon" "$OUT"
|
||
ck T1b "iface:lo kind=lo up=true" "$OUT"
|
||
ck T1c "iface:wlan0 kind=wifi up=true" "$OUT"
|
||
ck T1d "ip=10.78.193.50" "$OUT" # 若 iface 行 ip 解析成功(ip 桩已修)——实际由 wlan gw 行给,见下
|
||
ck T1e "gw=10.194.61.111" "$OUT"
|
||
ck T1f "wifi connected=1 state=COMPLETED ssid=MyWiFi" "$OUT"
|
||
ck T1g "bt available=1 powered=1 address=00:1A:7D:DA:71:13 paired=2" "$OUT"
|
||
ck T1h "rfkill:wlan soft=0 hard=0" "$OUT"
|
||
ck T1i "rfkill:bluetooth soft=1 hard=0" "$OUT"
|
||
|
||
# ---- T2: iface 单/全 ----
|
||
OUT=$(env $ENVS $Q "$T/meow_net" iface wlan0 2>&1)
|
||
ck T2a '"name":"wlan0"' "$OUT"
|
||
ck T2b '"kind":"wifi"' "$OUT"
|
||
ck T2c '"ip":"10.78.193.50"' "$OUT"
|
||
OUT=$(env $ENVS $Q "$T/meow_net" iface 2>&1)
|
||
ck T2d '"name":"lo"' "$OUT"
|
||
|
||
# ---- T3: wifi networks(读级)----
|
||
OUT=$(env $ENVS $Q "$T/meow_net" wifi networks 2>&1)
|
||
ck T3a "MyWiFi" "$OUT"
|
||
|
||
# ---- T4: wifi scan(写级;宿主 CLI=CALL_OTHER → 拒)----
|
||
OUT=$(env $ENVS $Q "$T/meow_net" wifi scan 2>&1)
|
||
ck T4a "permission denied" "$OUT"
|
||
|
||
# ---- T5: bt status / bt paired(读级)----
|
||
OUT=$(env $ENVS $Q "$T/meow_net" bt status 2>&1)
|
||
ck T5a "available=1 powered=1" "$OUT"
|
||
ck T5b "paired=2" "$OUT"
|
||
OUT=$(env $ENVS $Q "$T/meow_net" bt paired 2>&1)
|
||
ck T5c "My Headset" "$OUT"
|
||
ck T5d "Speaker" "$OUT"
|
||
|
||
# ---- T6: HibyOS 只读降级(读可查,写拒)----
|
||
echo hiby > "$T/boot_mode"
|
||
sleep 2 # 等守护下一拍热切换
|
||
OUT=$(env $ENVS $Q "$T/meow_net" status 2>&1)
|
||
ck T6a "mode=readonly" "$OUT"
|
||
ck T6b "iface:wlan0" "$OUT" # 读侧仍可查
|
||
OUT=$(env $ENVS $Q "$T/meow_net" wifi networks 2>&1)
|
||
ck T6c "MyWiFi" "$OUT" # 读级子命令仍可用
|
||
OUT=$(env $ENVS $Q "$T/meow_net" wifi on 2>&1); RC=$?
|
||
ck T6d "permission denied" "$OUT"
|
||
echo meow > "$T/boot_mode"
|
||
sleep 2
|
||
OUT=$(env $ENVS $Q "$T/meow_net" status 2>&1)
|
||
ck T6e "mode=meow" "$OUT" # 热切换回全功能
|
||
|
||
# ---- T7: 守护日志(每次开机新文件;接口 add/写拒绝 必记)----
|
||
sleep 1
|
||
LOGS=$(ls "$T/logs"/net_*.log 2>/dev/null | head -1)
|
||
[ -n "$LOGS" ] && { PASS=$((PASS+1)); echo "PASS T7a log file: $(basename "$LOGS")"; } || { FAIL=$((FAIL+1)); echo "FAIL T7a 无日志文件"; }
|
||
[ -n "$LOGS" ] && { grep -q "iface add kind=wifi name=wlan0" "$LOGS" && { PASS=$((PASS+1)); echo "PASS T7b iface add 已记"; } || { FAIL=$((FAIL+1)); echo "FAIL T7b 未记 iface add"; }; }
|
||
|
||
# ---- T8: 守护停 → CLI help 本地可用;status 报守护不可达 ----
|
||
kill $DPID 2>/dev/null; wait $DPID 2>/dev/null; DPID=""
|
||
sleep 0.5
|
||
OUT=$(env $ENVS $Q "$T/meow_net" help 2>&1)
|
||
ck T8a "usage: meow_net" "$OUT"
|
||
OUT=$(env $ENVS $Q "$T/meow_net" status 2>&1)
|
||
ck T8b "守护不可达" "$OUT"
|
||
|
||
# ---- T9: 无参 → help;未知子命令 → usage ----
|
||
OUT=$(env $ENVS $Q "$T/meow_net" 2>&1)
|
||
ck T9a "usage: meow_net" "$OUT"
|
||
OUT=$(env $ENVS $Q "$T/meow_net" bogus 2>&1); RC=$?
|
||
ck T9b "usage: meow_net" "$OUT"
|
||
|
||
# ---- 重启 daemon A(T8 已停)供期2 观测/连接表/日志测试 ----
|
||
env $ENVS $Q "$BIN" --sock "$T/net.sock" >"$T/daemon2.log" 2>&1 &
|
||
DPID=$!
|
||
for i in $(seq 1 30); do [ -S "$T/net.sock" ] && break; sleep 0.2; done
|
||
[ -S "$T/net.sock" ] || { echo "FAIL T10-pre: daemon 未重启"; cat "$T/daemon2.log"; exit 1; }
|
||
|
||
# ---- T10: 期2 conns(读级;观测层经 MEOW_TCP/UDP 桩 + amsd/svcd 缺省 → proc:unknown 归因)----
|
||
sleep 1 # 等守护普查一拍
|
||
OUT=$(env $ENVS $Q "$T/meow_net" conns 2>&1)
|
||
ck T10a "proc:unknown" "$OUT"
|
||
ck T10b "10.78.193.50:20791" "$OUT"
|
||
ck T10b2 "140.205.5.9:443" "$OUT"
|
||
ck T10c "ESTAB" "$OUT"
|
||
ck T10d "UDP" "$OUT"
|
||
ck T10e "connection" "$OUT"
|
||
# ---- T11: apps(实体聚合)----
|
||
OUT=$(env $ENVS $Q "$T/meow_net" apps 2>&1)
|
||
ck T11a "entity" "$OUT"
|
||
ck T11b "proc:unknown" "$OUT"
|
||
# ---- T12: dns status/stats(DNS 禁用 → 显示 disabled)----
|
||
OUT=$(env $ENVS $Q "$T/meow_net" dns status 2>&1)
|
||
ck T12a "proxy disabled" "$OUT"
|
||
OUT=$(env $ENVS $Q "$T/meow_net" dns stats 2>&1)
|
||
ck T12b "proxy disabled" "$OUT"
|
||
# ---- T13: dns flush(写级;宿主 CLI=CALL_OTHER → 拒)----
|
||
OUT=$(env $ENVS $Q "$T/meow_net" dns flush 2>&1)
|
||
ck T13a "permission denied" "$OUT"
|
||
|
||
# ---- T13b: 端到端 JSON 合法性(STATUS_0xE0 / IFACE_0xE2 可被完整解析,括号配对/无尾逗号)----
|
||
JOUT=$(python3 - "$T/net.sock" <<'PYEOF'
|
||
import socket,struct,sys,json
|
||
s=socket.socket(socket.AF_UNIX,socket.SOCK_STREAM); s.connect(sys.argv[1]); s.settimeout(2)
|
||
def recvn(n):
|
||
d=b""
|
||
while len(d)<n:
|
||
c=s.recv(n-len(d))
|
||
if not c: return d
|
||
d+=c
|
||
return d
|
||
def req(typ,payload=b""):
|
||
s.sendall(struct.pack('<IHHII',0x4D4F5701,1,typ,1,len(payload))+payload)
|
||
H=struct.unpack('<IHHII', recvn(16)); body=recvn(H[4])
|
||
code,jlen=struct.unpack('<IH',body[:6]); return body[8:8+jlen].decode('utf-8','replace')
|
||
ok=1
|
||
for nm,typ,pl in [("STATUS",0x00E0,b""),("IFACE_ALL",0x00E2,b"\x00"*32),("IFACE_WLAN",0x00E2,b"wlan0"+b"\x00"*27)]:
|
||
js=req(typ,pl)
|
||
try:
|
||
json.loads(js); sys.stdout.write("%s VALID\n" % nm)
|
||
except Exception as e:
|
||
sys.stdout.write("%s INVALID %s\n" % (nm,e))
|
||
PYEOF
|
||
)
|
||
ck T13b "STATUS VALID" "$JOUT"
|
||
ck T13c "IFACE_ALL VALID" "$JOUT"
|
||
ck T13d "IFACE_WLAN VALID" "$JOUT"
|
||
echo "$JOUT" | grep -q "INVALID" && { FAIL=$((FAIL+1)); echo "FAIL T13e 存在无效 JSON"; } || { PASS=$((PASS+1)); echo "PASS T13e no INVALID"; }
|
||
|
||
# ---- T15: apps 无原始端点(tcp 桩含 inode=0 未归因 → proc:unknown,绝不落成 IP:port entity)----
|
||
OUT=$(env $ENVS $Q "$T/meow_net" conns 2>&1)
|
||
ck T15a "10.78.195.50:443" "$OUT" # inode=0 的连接仍在表中
|
||
OUT=$(env $ENVS $Q "$T/meow_net" apps 2>&1)
|
||
ck T15b "proc:unknown" "$OUT"
|
||
echo "$OUT" | grep -qE '^[0-9][0-9.]*:' && { FAIL=$((FAIL+1)); echo "FAIL T15c apps 出现原始端点行"; } || { PASS=$((PASS+1)); echo "PASS T15c no raw endpoint row"; }
|
||
|
||
# ---- T16: policy(读级 show 任意调用者;写级仅系统身份 → 宿主 CLI=CALL_OTHER 拒)----
|
||
OUT=$(env $ENVS $Q "$T/meow_net" policy show 2>&1)
|
||
ck T16a "app:dev.player.ncm" "$OUT"
|
||
ck T16b "domain=" "$OUT"
|
||
OUT=$(env $ENVS $Q "$T/meow_net" policy set app:dev.player.ncm allow 2>&1); RC=$?
|
||
ck T16c "permission denied" "$OUT"
|
||
[ $RC -eq 1 ] && { PASS=$((PASS+1)); echo "PASS T16d rc=1"; } || { FAIL=$((FAIL+1)); echo "FAIL T16d rc=$RC"; }
|
||
OUT=$(env $ENVS $Q "$T/meow_net" policy domain app:dev.player.ncm +x 2>&1)
|
||
ck T16e "permission denied" "$OUT"
|
||
OUT=$(env $ENVS $Q "$T/meow_net" policy del app:dev.player.ncm 2>&1)
|
||
ck T16f "permission denied" "$OUT"
|
||
|
||
# ---- T17: SDK 自愿通道 end-to-end(meow_net_policy_check/report 对守护 A)----
|
||
SDK_BIN="$T/test_net_ipc"
|
||
if [ -n "$Q" ]; then
|
||
"$HOME/Project/R3ProII/.tools/zig-mipsel-cc" -Os -Wall -Wextra -I../sdk -I../sdk/include -I../meow_launcherd \
|
||
../sdk/test_net_ipc.c ../sdk/meow_net_ipc.c -o "$SDK_BIN" 2>/dev/null
|
||
else
|
||
cc -Os -Wall -Wextra -I../sdk -I../sdk/include -I../meow_launcherd \
|
||
../sdk/test_net_ipc.c ../sdk/meow_net_ipc.c -o "$SDK_BIN" 2>/dev/null
|
||
fi
|
||
if [ -x "$SDK_BIN" ]; then
|
||
OUT=$(env MEOW_LOG_APP=dev.player.ncm MEOW_NET_SOCK="$T/net.sock" $Q "$SDK_BIN" 2>&1)
|
||
ck T17a "CHECK_GOOD=0" "$OUT" # music.163.com 放行
|
||
ck T17b "CHECK_BLOCK=1" "$OUT" # ads.example.com 被策略 deny → block
|
||
ck T17c "REPORT_DONE" "$OUT"
|
||
else
|
||
FAIL=$((FAIL+1)); echo "FAIL T17 SDK test 构建失败"
|
||
fi
|
||
|
||
# ---- T18: SDK report → status JSON entity_bytes 回读 ----
|
||
JOUT2=$(python3 - "$T/net.sock" <<'PYEOF'
|
||
import socket,struct,sys,json
|
||
s=socket.socket(socket.AF_UNIX,socket.SOCK_STREAM); s.connect(sys.argv[1]); s.settimeout(2)
|
||
def recvn(n):
|
||
d=b""
|
||
while len(d)<n:
|
||
c=s.recv(n-len(d))
|
||
if not c: return d
|
||
d+=c
|
||
return d
|
||
s.sendall(struct.pack('<IHHII',0x4D4F5701,1,0x00E0,1,0))
|
||
H=struct.unpack('<IHHII', recvn(16)); body=recvn(H[4])
|
||
code,jlen=struct.unpack('<IH',body[:6]); js=body[8:8+jlen].decode('utf-8','replace')
|
||
o=json.loads(js)
|
||
eb=o.get("entity_bytes") or []
|
||
hit=[e for e in eb if e["entity"]=="app:dev.player.ncm"]
|
||
sys.stdout.write("EB_HIT=%d RX=%d TX=%d\n" % (len(hit), hit[0]["rx"] if hit else -1, hit[0]["tx"] if hit else -1))
|
||
PYEOF
|
||
)
|
||
ck T18a "EB_HIT=1" "$JOUT2"
|
||
ck T18b "RX=12345" "$JOUT2"
|
||
ck T18c "TX=67890" "$JOUT2"
|
||
# ---- RSSI 回读:status wifi rssi 应 >=0(signal_poll 桩已给)----
|
||
OUT=$(env $ENVS $Q "$T/meow_net" status 2>&1)
|
||
ck T18d "rssi=-45" "$OUT"
|
||
|
||
# ---- T14: DNS 代理 wire 实测(守护 B:高端口 + 桩上游 + 全局 deny;测 deny/forward/cache)----
|
||
HOSTIP=$(hostname -I 2>/dev/null | awk '{print $1}')
|
||
[ -n "$HOSTIP" ] || HOSTIP="127.0.0.1"
|
||
cat > "$T/policy_dns" <<'EOF'
|
||
global domain=-ads.example.com dns.filter_aaaa=1
|
||
EOF
|
||
printf 'nameserver %s\n' "$HOSTIP" > "$T/resolv_dns"
|
||
cat > "$T/dns_test.py" <<'PYEOF'
|
||
import socket, struct, threading, sys, os
|
||
UP_IP = os.environ.get("T_UP_IP", "0.0.0.0")
|
||
up = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||
up.bind((UP_IP, 5311)) # 0.0.0.0 通配,绑到宿主自身 IP
|
||
up.settimeout(6)
|
||
def serve():
|
||
try:
|
||
while True:
|
||
d,a = up.recvfrom(1536)
|
||
off=12
|
||
while d[off]!=0: off += 1+d[off]
|
||
off += 1+4
|
||
qsec = d[12:off]
|
||
resp = d[:2] + b'\x81\x80' + b'\x00\x01\x00\x01\x00\x00\x00\x00' + qsec
|
||
resp += b'\xc0\x0c' + b'\x00\x01\x00\x01' + struct.pack('>I',60) + b'\x00\x04' + socket.inet_aton('11.22.33.44')
|
||
up.sendto(resp, a)
|
||
except Exception:
|
||
pass
|
||
threading.Thread(target=serve, daemon=True).start()
|
||
def query(name, qtype=1):
|
||
s=socket.socket(socket.AF_INET, socket.SOCK_DGRAM); s.settimeout(3)
|
||
hdr=b'\x12\x34'+b'\x01\x00'+b'\x00\x01\x00\x00\x00\x00\x00\x00'
|
||
q=b''.join(bytes([len(l)])+l.encode() for l in name.split('.'))+b'\x00'+struct.pack('>HH',qtype,1)
|
||
s.sendto(hdr+q, ("127.0.0.1", 5300))
|
||
r,_=s.recvfrom(1536); rco=r[3]&0xf; an=struct.unpack('>H',r[6:8])[0]
|
||
return rco,an
|
||
try:
|
||
d1,a1 = query("ads.example.com") # deny → NXDOMAIN (rcode 3)
|
||
d2,a2 = query("music.163.com") # allow → forward → A 11.22.33.44
|
||
da,aa = query("music.163.com", 28) # AAAA + dns.filter_aaaa=1 → 空应答(回落 A)
|
||
sys.stdout.write("DENY_RCODE=%d\nALLOW_AN=%d\nAAAA_RCODE=%d AAAA_AN=%d\n" % (d1, a2, da, aa))
|
||
except Exception as e:
|
||
sys.stdout.write("ERR=%s\n" % e)
|
||
PYEOF
|
||
# 追加式覆写(env 左→右,后者胜出):DNS 启用、换独立 socket/resolv/policy、上游端口。
|
||
DNSENV="$ENVS MEOW_DNS_DISABLE=0 MEOW_NET_SOCK=$T/dns.sock MEOW_RESOLV=$T/resolv_dns
|
||
MEOW_NET_POLICY=$T/policy_dns MEOW_DNS_PORT=5300 MEOW_DNS_UPSTREAM_PORT=5311"
|
||
ln -sf "$(readlink -f "$BIN")" "$T/dns_netmgrd"
|
||
env $DNSENV $Q "$BIN" --sock "$T/dns.sock" >"$T/dnsd.log" 2>&1 &
|
||
D2PID=$!
|
||
for i in $(seq 1 30); do [ -S "$T/dns.sock" ] && break; sleep 0.2; done
|
||
sleep 1
|
||
OUT=$(env $DNSENV $Q "$T/meow_net" dns status 2>&1)
|
||
ck T14a "enabled=1 upstream=$HOSTIP" "$OUT"
|
||
WIRE=$(python3 "$T/dns_test.py" 2>&1)
|
||
ck T14b "DENY_RCODE=3" "$WIRE"
|
||
ck T14c "ALLOW_AN=1" "$WIRE"
|
||
ck T14c2 "AAAA_RCODE=0" "$WIRE" # 期4 AAAA 过滤:rcode 0
|
||
ck T14c3 "AAAA_AN=0" "$WIRE" # 且 0 条应答(回落 A)
|
||
OUT=$(env $DNSENV $Q "$T/meow_net" dns stats 2>&1)
|
||
ck T14d "q=3" "$OUT" # deny + allow + AAAA = 3 查询
|
||
ck T14e "deny=1" "$OUT"
|
||
kill $D2PID 2>/dev/null; wait $D2PID 2>/dev/null
|
||
# 恢复守护 A 的 MEOW_RESOLV(其未被 DNS 触碰,此处确认)
|
||
grep -q "nameserver 223.5.5.5" "$T/resolv" && { PASS=$((PASS+1)); echo "PASS T14f daemonA resolv untouched"; } || { FAIL=$((FAIL+1)); echo "FAIL T14f daemonA resolv touched"; }
|
||
|
||
echo "=============================="
|
||
echo "PASS=$PASS FAIL=$FAIL"
|
||
[ $FAIL -eq 0 ]
|