Files
MeowOS-For-R3P2/patch_v2/meow_netmgrd/netmgrd_authtest.c
T
MeowOS 79a0fed336 meow_netmgrd 期1:网络管理服务骨架+接口统一层+CLI+IPC+日志框架
NETMGR_DESIGN.md 期1范围(→ M6.0)落地:
- meow_netmgrd 守护:svcd 托管 trigger=boot/restart=on-fail,进程内 HibyOS 只读降级
  (/tmp/meow_boot_mode != meow → 读可查/写拒+日志,热切换)。
- 接口统一层(§3):iface 枚举(/sys/class/net+/proc/net/dev,lo/wlan0/usb-eth 热插拔节拍检测);
  WiFi 状态/扫描/网络列表/连接/断开(wpa_cli popen 有界收割防挂死,257 教训);IP/路由/DNS 只读
  (ip 优先 /proc/net/route+resolv.conf);BT 状态/开关/已配对(hciconfig/bluetoothctl);rfkill 读写;udhcpc 续租/释放(MeowOS)。
- IPC 0x00E0-0x00E7(STATUS/IFACE/WIFI_CTL/BT_CTL+各自 RESULT):读级任意、写级仅系统身份(SO_PEERCRED
  同 svc_power),0xE8-0xEF 期2/3 预留(仅注释)。
- CLI 双形态 meow_net(status/iface/wifi/bt/rfkill/help):IPC 薄壳,help 本地必可用。
- 日志框架:TF MeowOS/logs/net_<bootts>.log(无卡降级 /tmp),接口状态变化/写操作必记。
- 单线程 poll、静态表、热路径禁 malloc;mipsel 静态(0 warning),宿主+qemu-mipsel 全过,
  真机只读验证 status/wifi scan/bt status 正确。

meow_ipc.h 仅追加 0x00E0-0x00E7 段(不改既有行)。
2026-09-01 19:55:26 +08:00

219 lines
12 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* netmgrd_authtest.c — meow_netmgrd IPC 鉴权/写级决策 宿主自测(本程序非生产代码)。
*
* 通过 #include 生产源文件(meow_netmgrd.c,用 #define main 改名避免入口冲突),在同一 TU 内直接
* 访问其 FILE-STATIC 函数/全局:classify_exe / is_sys_identity / wifi_cmd_is_write / bt_cmd_is_write /
* wifi_write_authorize / bt_write_authorize / rfkill_set_block / wifi_networks / wifi_scan / bt_status,
* 验证鉴别/分级/授权决策表与接口层动作(假 sysfs/proc + 桩命令)。
* 覆盖「真机需特权路径 /proc/pid/exe 判定」之外的所有纯逻辑分支;真实 pid→exe 解析留真机验证。
*
* 用途:dev docs 复现级宿主自测;不进入固件/不部署。用法:
* cc -Wall -Wextra -I../meow_launcherd netmgrd_authtest.c -o netmgrd_authtest && ./netmgrd_authtest
*/
#define main meow_netmgrd_prod_main_unused
#include "meow_netmgrd.c"
#undef main
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
static int g_fail = 0;
#define CHECK(cond) do { if (!(cond)) { printf(" FAIL: %s (line %d)\n", #cond, __LINE__); g_fail++; } \
else { printf(" ok : %s\n", #cond); } } while (0)
static void wf(const char *p, const char *s)
{
FILE *f = fopen(p, "w");
if (f) { fputs(s, f); fclose(f); }
}
int main(void)
{
static const char *T = "/tmp/nmg_authtest";
char p[192];
caller_t c;
printf("== classify_exe ==\n");
memset(&c, 0, sizeof c);
classify_exe("/usr/data/mnt/sd_0/MeowAPPs/os.meow.tst/meow", &c);
CHECK(c.kind == CALL_PKG && strcmp(c.pkg, "os.meow.tst") == 0);
memset(&c, 0, sizeof c);
classify_exe("/usr/data/mnt/sd_0/MeowAPPs/com.example.tool/meow", &c);
CHECK(c.kind == CALL_PKG && strcmp(c.pkg, "com.example.tool") == 0);
memset(&c, 0, sizeof c);
classify_exe("/usr/data/mnt/sd_0/MeowAPPs/os.meow.tst/sub/meow", &c);
CHECK(c.kind == CALL_PKG && strcmp(c.pkg, "os.meow.tst") == 0);
memset(&c, 0, sizeof c);
classify_exe("/usr/bin/meow_net", &c);
CHECK(c.kind == CALL_SYS && strcmp(c.pkg, "meow_net") == 0); /* /usr/bin/meow_* 前缀 → 系统 */
memset(&c, 0, sizeof c);
classify_exe("/usr/bin/meow_launcherd", &c);
CHECK(c.kind == CALL_SYS && strcmp(c.pkg, "os.meow.launcher") == 0);
memset(&c, 0, sizeof c);
classify_exe("/usr/bin/wpa_cli", &c);
CHECK(c.kind == CALL_OTHER); /* 非 meow_* 系统二进制 */
memset(&c, 0, sizeof c);
classify_exe("/usr/data/mnt/sd_0/MeowAPPs/justadirty/k", &c);
CHECK(c.kind == CALL_PKG && strcmp(c.pkg, "justadirty") == 0); /* 第三方包(非 os.meow.*) */
CHECK(is_sys_identity(&c) == 0);
printf("== is_sys_identity ==\n");
c.kind = CALL_PKG; snprintf(c.pkg, sizeof c.pkg, "%s", "os.meow.tst");
CHECK(is_sys_identity(&c) == 1);
c.kind = CALL_PKG; snprintf(c.pkg, sizeof c.pkg, "%s", "com.example.tool");
CHECK(is_sys_identity(&c) == 0);
c.kind = CALL_SYS; snprintf(c.pkg, sizeof c.pkg, "%s", "os.meow.launcher");
CHECK(is_sys_identity(&c) == 1);
c.kind = CALL_OTHER; c.pkg[0] = 0;
CHECK(is_sys_identity(&c) == 0);
printf("== wifi_cmd_is_write / bt_cmd_is_write ==\n");
CHECK(wifi_cmd_is_write("status", NULL) == 0);
CHECK(wifi_cmd_is_write("networks", NULL) == 0);
CHECK(wifi_cmd_is_write("scan", NULL) == 1);
CHECK(wifi_cmd_is_write("connect", "ssid") == 1);
CHECK(wifi_cmd_is_write("disconnect", NULL) == 1);
CHECK(wifi_cmd_is_write("on", NULL) == 1);
CHECK(wifi_cmd_is_write("off", NULL) == 1);
CHECK(wifi_cmd_is_write("rfkill", "list") == 0);
CHECK(wifi_cmd_is_write("rfkill", "wlan on") == 1);
CHECK(wifi_cmd_is_write("udhcpc", "renew wlan0") == 1);
CHECK(bt_cmd_is_write("status") == 0);
CHECK(bt_cmd_is_write("paired") == 0);
CHECK(bt_cmd_is_write("on") == 1);
CHECK(bt_cmd_is_write("off") == 1);
printf("== authorize 决策(系统身份 × MeowOS 模式)==\n");
caller_t sys; memset(&sys, 0, sizeof sys); sys.kind = CALL_SYS; snprintf(sys.pkg, sizeof sys.pkg, "%s", "meow_net");
caller_t pkgm; memset(&pkgm, 0, sizeof pkgm); pkgm.kind = CALL_PKG; snprintf(pkgm.pkg, sizeof pkgm.pkg, "%s", "os.meow.panel");
caller_t third; memset(&third, 0, sizeof third); third.kind = CALL_PKG; snprintf(third.pkg, sizeof third.pkg, "%s", "com.example.tool");
caller_t other; memset(&other, 0, sizeof other); other.kind = CALL_OTHER; other.uid = 1000;
/* 读级:任意放行,与身份/模式无关 */
CHECK(wifi_write_authorize(&other, 0, "networks", NULL) == MEOW_OK);
CHECK(bt_write_authorize(&other, 0, "status") == MEOW_OK);
CHECK(wifi_write_authorize(&third, 1, "rfkill", "list") == MEOW_OK);
/* 写级:only 系统身份 + meow 模式 */
CHECK(wifi_write_authorize(&sys, 1, "on", NULL) == MEOW_OK);
CHECK(wifi_write_authorize(&pkgm, 1, "connect", "ssid") == MEOW_OK);
CHECK(bt_write_authorize(&sys, 1, "off") == MEOW_OK);
CHECK(wifi_write_authorize(&third, 1, "scan", NULL) == MEOW_ERR_PERM); /* 第三方包 → 拒 */
CHECK(wifi_write_authorize(&other, 1, "on", NULL) == MEOW_ERR_PERM); /* CALL_OTHER + uid → 拒 */
CHECK(wifi_write_authorize(&sys, 0, "on", NULL) == MEOW_ERR_PERM); /* HibyOS 只读 → 拒 */
CHECK(bt_write_authorize(&sys, 0, "on") == MEOW_ERR_PERM); /* HibyOS 只读 → 拒 */
CHECK(bt_write_authorize(&pkgm, 1, "off") == MEOW_OK);
printf("== 接口层动作(假 sysfs + 桩命令)==\n");
/* 搭假 /sys/class/net + rfkill + bt(先建祖先目录) */
mkdir(T, 0755);
snprintf(p, sizeof p, "%s/net", T); mkdir(p, 0755);
snprintf(p, sizeof p, "%s/net/lo", T); mkdir(p, 0755);
snprintf(p, sizeof p, "%s/net/wlan0", T); mkdir(p, 0755);
snprintf(p, sizeof p, "%s/rfkill", T); mkdir(p, 0755);
snprintf(p, sizeof p, "%s/rfkill/rfkill0", T); mkdir(p, 0755);
snprintf(p, sizeof p, "%s/bt", T); mkdir(p, 0755);
snprintf(p, sizeof p, "%s/bt/hci0", T); mkdir(p, 0755);
snprintf(p, sizeof p, "%s/net/lo/operstate", T); wf(p, "up\n");
snprintf(p, sizeof p, "%s/net/wlan0/operstate", T); wf(p, "up\n");
snprintf(p, sizeof p, "%s/rfkill/rfkill0/type", T); wf(p, "wlan\n");
snprintf(p, sizeof p, "%s/rfkill/rfkill0/soft", T); wf(p, "0\n");
snprintf(p, sizeof p, "%s/rfkill/rfkill0/hard", T); wf(p, "0\n");
snprintf(p, sizeof p, "%s/bt/hci0/address", T); wf(p, "00:1A:7D:DA:71:13\n");
snprintf(p, sizeof p, "%s/bt/hci0/power", T); wf(p, "on\n");
snprintf(p, sizeof p, "%s/netdev", T); wf(p, "Inter-| Receive | Transmit\n lo: 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0\n wlan0: 5000000 5000 0 0 0 0 0 0 1000000 1000 0 0 0 0 0 0\n");
snprintf(p, sizeof p, "%s/route", T); wf(p, "Iface\tDestination\tGateway \tFlags\nwlan0\t005EC20A\t6F3DC20A\t0003\nlo\t0100007F\t00000000\t0001\n");
snprintf(p, sizeof p, "%s/resolv", T); wf(p, "nameserver 223.5.5.5\nnameserver 10.78.193.1\n");
snprintf(p, sizeof p, "%s/boot_mode", T); wf(p, "meow\n");
/* 桩工具 */
snprintf(p, sizeof p, "%s/wpa_cli", T); wf(p,
"#!/bin/sh\n"
"case \"$1\" in\n"
" status) echo 'wpa_state=COMPLETED'; echo 'ssid=MyWiFi'; echo 'ip_address=10.78.193.50'; echo 'signal=-45';;\n"
" scan) echo OK;;\n"
" scan_results) echo 'bssid / frequency / signal / flags / ssid'; echo 'xx:xx / 2412 / -50 / WPA2 / TestAP';;\n"
" list_networks) echo 'network id / ssid / bssid / flags'; echo '0\tMyWiFi\tany\t[CURRENT]';;\n"
" add_network) echo 5;;\n"
" set_network) echo OK;;\n"
" enable_network) echo OK;;\n"
" select_network) echo OK;;\n"
" disconnect) echo OK;;\n"
"esac\n"
"exit 0\n");
snprintf(p, sizeof p, "%s/hciconfig", T); wf(p,
"#!/bin/sh\n"
"echo 'hci0: Type: Primary Bus: USB'\n"
"echo ' BD Address: 00:1A:7D:DA:71:13 ACL MTU: 1021:8'\n"
"echo ' UP RUNNING PSCAN'\n");
snprintf(p, sizeof p, "%s/bluetoothctl", T); wf(p,
"#!/bin/sh\n"
"echo 'Device 00:1A:7D:DA:71:13 My Headset'\n"
"echo 'Device 11:22:33:44:55:66 Speaker'\n");
snprintf(p, sizeof p, "%s/ip", T); wf(p,
"#!/bin/sh\n"
"if [ \"$6\" = \"wlan0\" ]; then echo \"2: wlan0 inet 10.78.193.50/24 brd 255.255.255.255 scope global wlan0\"; fi\n"
"exit 0\n");
snprintf(p, sizeof p, "%s/wpa_cli", T); chmod(p, 0755);
snprintf(p, sizeof p, "%s/hciconfig", T); chmod(p, 0755);
snprintf(p, sizeof p, "%s/bluetoothctl", T); chmod(p, 0755);
snprintf(p, sizeof p, "%s/ip", T); chmod(p, 0755);
g_net_dir[0] = 0; snprintf(g_net_dir, sizeof g_net_dir, "%s/net", T);
g_netdev[0] = 0; snprintf(g_netdev, sizeof g_netdev, "%s/netdev", T);
g_net_route[0] = 0; snprintf(g_net_route, sizeof g_net_route, "%s/route", T);
g_resolv[0] = 0; snprintf(g_resolv, sizeof g_resolv, "%s/resolv", T);
g_rfkill_dir[0] = 0; snprintf(g_rfkill_dir, sizeof g_rfkill_dir, "%s/rfkill", T);
g_bt_dir[0] = 0; snprintf(g_bt_dir, sizeof g_bt_dir, "%s/bt", T);
g_boot_mode[0] = 0; snprintf(g_boot_mode, sizeof g_boot_mode, "%s/boot_mode", T);
g_wpa_cli = ""; { char x[160]; snprintf(x, sizeof x, "%s/wpa_cli", T); static char wc[160]; snprintf(wc, sizeof wc, "%s", x); g_wpa_cli = wc; }
g_hciconfig = ""; { char x[160]; snprintf(x, sizeof x, "%s/hciconfig", T); static char hc[160]; snprintf(hc, sizeof hc, "%s", x); g_hciconfig = hc; }
g_bluetoothctl = ""; { char x[160]; snprintf(x, sizeof x, "%s/bluetoothctl", T); static char bc[160]; snprintf(bc, sizeof bc, "%s", x); g_bluetoothctl = bc; }
g_ip = ""; { char x[160]; snprintf(x, sizeof x, "%s/ip", T); static char ip[160]; snprintf(ip, sizeof ip, "%s", x); g_ip = ip; }
/* rfkill_set_block:wlan → soft=1 */
CHECK(rfkill_set_block("wlan", 1) == 0);
snprintf(p, sizeof p, "%s/rfkill/rfkill0/soft", T);
char rb[8]; read_file_txt(p, rb, sizeof rb);
CHECK(strcmp(rb, "1") == 0);
/* enum_ifaces(detail=1):ip/gw/rx/tx */
enum_ifaces(1);
CHECK(g_iface_n >= 2);
int wlan = -1;
for (int i = 0; i < g_iface_n; i++) if (!strcmp(g_ifaces[i].name, "wlan0")) wlan = i;
CHECK(wlan >= 0);
CHECK(strcmp(g_ifaces[wlan].kind, "wifi") == 0);
CHECK(g_ifaces[wlan].up == 1);
CHECK(strcmp(g_ifaces[wlan].gw, "10.194.61.111") == 0); /* 0x6F3DC20A LE → 10.194.61.111 */
CHECK(g_ifaces[wlan].rx == 5000000);
/* wifi_networks(读) + wifi_scan(写执行路径) */
ctl_result_t r;
wifi_networks(&r);
CHECK(r.code == MEOW_OK && strstr(r.text, "MyWiFi") != NULL);
wifi_scan(&r);
CHECK(r.code == MEOW_OK && strstr(r.text, "TestAP") != NULL);
/* bt_status:available=1 powered=1 address=... paired=2 */
bt_t b;
bt_status(&b);
CHECK(b.available == 1 && b.powered == 1);
CHECK(strcmp(b.address, "00:1A:7D:DA:71:13") == 0);
CHECK(b.paired_n == 2);
/* 写级执行(wifi_onoff off → rfkill block wlan)已在 rfkill_set_block 覆盖;此处联调 wifi_ctl_execute */
wifi_ctl_execute("networks", NULL, &r);
CHECK(r.code == MEOW_OK && strstr(r.text, "MyWiFi") != NULL);
/* connect:现有 ssid 复用(enable+select,network_id=0);新 ssid 走 add/set/enable/select(id=5)。 */
wifi_ctl_execute("connect", "MyWiFi", &r);
CHECK(r.code == MEOW_OK && strstr(r.text, "ssid=MyWiFi") != NULL && strstr(r.text, "network_id=0") != NULL);
wifi_ctl_execute("connect", "NewAP,secret", &r);
CHECK(r.code == MEOW_OK && strstr(r.text, "ssid=NewAP") != NULL && strstr(r.text, "network_id=5") != NULL);
wifi_ctl_execute("disconnect", NULL, &r);
CHECK(r.code == MEOW_OK);
if (g_fail) { printf("\nNETMGR AUTH TEST: %d FAIL\n", g_fail); return 1; }
printf("\nNETMGR AUTH TEST: ALL PASS\n");
return 0;
}