/* test_daemoncfg.c — vmsigd config parser + admission policy (WS4). Config parse is pure; * admission is exercised against a live discovery (fake probe + recording sink) so the * vmid->endpoint resolution at connect time is verified end-to-end without armed adapters. */ #define _GNU_SOURCE #include "vmsig.h" #include "discovery.h" #include "vmsigd.h" #include "vmsigd_admission.h" #include #include #include #include #include static int g_fail = 0; #define CHECK(cond, msg) do { if (!(cond)) { printf(" FAIL: %s\n", (msg)); g_fail = 1; } } while (0) static void test_config(void) { printf("test_config\n"); const char* sample = "# vmsigd config\n" "socket = /run/foo.sock\n" "watch = /dev/shm/vmsig\n" "pve_conf = /etc/pve/qemu-server\n" "\n" "[grant uid=0]\n" "vmids = *\n" "caps = observe,input,memctx,roster\n" "arb_prio = 100\n" "[grant uid=1000]\n" "vmids = 101, 102\n" "caps = observe\n" "arb_prio = 50\n"; vmsigd_config c; vmsigd_config_defaults(&c); CHECK(vmsigd_config_parse_buf(&c, sample) == 0, "parse ok"); CHECK(strcmp(c.socket, "/run/foo.sock") == 0, "global socket override"); CHECK(strcmp(c.qmp_dir, "/var/run/qemu-server") == 0, "default qmp_dir retained"); CHECK(c.ngrants == 2, "two grant stanzas"); CHECK(c.grants[0].uid == 0 && c.grants[0].all_vms, "grant0 uid=0 vmids=*"); CHECK(c.grants[0].cap_mask == (VMSIG_CAP_OBSERVE | VMSIG_CAP_INPUT | VMSIG_CAP_MEMCTX | VMSIG_CAP_ROSTER), "grant0 caps parsed"); CHECK(c.grants[0].arb_prio == 100, "grant0 arb_prio"); CHECK(c.grants[1].uid == 1000 && !c.grants[1].all_vms && c.grants[1].nvmids == 2 && c.grants[1].vmids[0] == 101 && c.grants[1].vmids[1] == 102, "grant1 vmid list"); CHECK(c.grants[1].cap_mask == VMSIG_CAP_OBSERVE, "grant1 caps"); CHECK(c.grants[1].arb_prio == 50, "grant1 arb_prio"); } /* ---- fake probe + recording sink (attach vmids to slots without armed adapters) ---- */ typedef struct { int dummy; } fakeprobe; static int fp_config(const vmsig_host_probe* p, uint32_t vmid, vmsig_host_facts* out) { (void)p; memset(out, 0, sizeof *out); out->vmid = vmid; out->share_on = 1; out->ok = 1; snprintf(out->name, sizeof out->name, "win-%u", vmid); return 0; } static int fp_live(const vmsig_host_probe* p, vmsig_host_facts* io) { (void)p; io->retry = 0; io->ok = 1; io->vm_state = VMSIG_VM_RUNNING; io->low = 0x80000000ull; return 0; } static int rs_attach(void* ud, vmsig_core* core, uint32_t vmid, uint32_t ep, const vmsig_host_facts* f) { (void)ud;(void)core;(void)vmid;(void)ep;(void)f; return 0; } static void rs_detach(void* ud, vmsig_core* core, uint32_t vmid, uint32_t ep) { (void)ud;(void)core;(void)vmid;(void)ep; } static void test_admission(void) { printf("test_admission\n"); vmsig_ctx* ctx = vmsig_ctx_new(); vmsig_core* core = vmsig_core_new(ctx); fakeprobe fpd; vmsig_host_probe probe = { fp_config, fp_live, &fpd }; vmsig_discovery_sink sink = { rs_attach, rs_detach, NULL }; char dir[] = "/tmp/vmsig_adm.XXXXXX"; CHECK(mkdtemp(dir) != NULL, "temp dir"); vmsig_discovery* disc = vmsig_discovery_new(core, dir, NULL, NULL, NULL, &probe, &sink); CHECK(disc != NULL, "discovery created"); vmsig_discovery_feed(disc, 101, 1); /* -> ep0 */ vmsig_discovery_feed(disc, 102, 1); /* -> ep1 */ vmsigd_config c; vmsigd_config_defaults(&c); vmsigd_config_parse_buf(&c, "[grant uid=0]\nvmids=*\ncaps=observe,input,memctx,roster\narb_prio=100\n" "[grant uid=1000]\nvmids=101,102\ncaps=observe\narb_prio=50\n" "[grant uid=1001]\nvmids=999\ncaps=observe\narb_prio=10\n"); vmsigd_admission adm = { &c, disc }; /* uid 0: all_vms => full mask */ vmsig_grant g0 = vmsigd_policy(0, 0, &adm); CHECK(g0.endpoint_mask == ~0ull, "uid0 (vmids=*) covers all endpoints"); CHECK(g0.cap_mask == (VMSIG_CAP_OBSERVE | VMSIG_CAP_INPUT | VMSIG_CAP_MEMCTX | VMSIG_CAP_ROSTER), "uid0 caps"); CHECK(g0.arb_prio == 100 && g0.principal == 0, "uid0 prio/principal"); /* uid 1000: vmids 101,102 attached at ep0,ep1 => bits 0,1 */ vmsig_grant g1 = vmsigd_policy(1000, 0, &adm); CHECK(g1.endpoint_mask == ((1ull << 0) | (1ull << 1)), "uid1000 resolved to ep0,ep1 bits"); CHECK(g1.cap_mask == VMSIG_CAP_OBSERVE && g1.arb_prio == 50, "uid1000 caps/prio"); /* uid 1001: vmid 999 not attached => no bits (peer learns via roster / reconnect) */ vmsig_grant g2 = vmsigd_policy(1001, 0, &adm); CHECK(g2.endpoint_mask == 0, "uid1001 unbound vmid => no endpoint bit yet"); /* unknown uid: empty grant => reject */ vmsig_grant g3 = vmsigd_policy(4242, 0, &adm); CHECK(g3.cap_mask == 0 && g3.endpoint_mask == 0, "unknown uid => empty grant (reject)"); vmsig_core_free(core); vmsig_ctx_free(ctx); rmdir(dir); } int main(void) { test_config(); test_admission(); printf("daemoncfg tests: %s\n", g_fail ? "FAIL" : "PASS"); return g_fail ? 1 : 0; }