ruvnet/RuView · error

ENOMEM

ENOMEM

Error message

veil: nl_socket_alloc failed

What it means

Identical daemon, vendored copy: `wifi-veil/` is the standalone workspace and its `firmware/openwrt/veil_shieldd.c` is byte-identical to `firmware/privshield/openwrt/veil_shieldd.c`. `veil_nl_connect` allocates a libnl socket with `nl_socket_alloc()`; a NULL return maps to `-ENOMEM`, aborting bring-up before any netlink traffic. The cause is heap exhaustion or a memory rlimit, not the netlink subsystem itself.

Source

Thrown at wifi-veil/firmware/openwrt/veil_shieldd.c:71

    struct nl_sock *sock;   /* generic-netlink socket to nl80211            */
    int             family; /* resolved "nl80211" genl family id           */
    int             ifindex;/* target AP interface (e.g. phy0-ap0)         */
    uint64_t        key;    /* shared session key for the keyed rotation    */
    size_t          passes; /* Givens passes                                */
    volatile sig_atomic_t running;
};

static struct veil_ctx g_ctx;

static void on_signal(int sig) { (void)sig; g_ctx.running = 0; }

/* ---------------------------------------------------------------------- */
/* nl80211 bring-up — all REAL libnl-genl-3 API names.                     */
/* ---------------------------------------------------------------------- */
static int veil_nl_connect(struct veil_ctx *c) {
    c->sock = nl_socket_alloc();
    if (!c->sock) {
        fprintf(stderr, "veil: nl_socket_alloc failed\n");
        return -ENOMEM;
    }
    if (genl_connect(c->sock)) {
        fprintf(stderr, "veil: genl_connect failed\n");
        return -EIO;
    }
    c->family = genl_ctrl_resolve(c->sock, "nl80211");
    if (c->family < 0) {
        fprintf(stderr, "veil: genl_ctrl_resolve(nl80211) failed: %d\n",
                c->family);
        return c->family;
    }
    /* Observe MLME events (auth/assoc, and — where the driver forwards them —
     * action-frame notifications). Real multicast group name is "mlme". */
    int grp = genl_ctrl_resolve_grp(c->sock, "nl80211", "mlme");
    if (grp >= 0) {
        (void)nl_socket_add_membership(c->sock, grp);
    }

View on GitHub (pinned to 4685618388)

Solutions

  1. Free memory or raise limits (stop unneeded services, install zram-swap, raise the cgroup cap) and restart.
  2. Check `dmesg` for OOM-killer activity around the start time.
  3. Verify `ldd` on this copy's binary matches the libnl3/libnl-genl3 packages present.

Example fix

# before
./veil_shieldd -i 2        # veil: nl_socket_alloc failed
# after
ulimit -v unlimited; /etc/init.d/veil_shieldd restart
Defensive patterns

Strategy: validation

Validate before calling

/* headroom check before daemon start */
#include <sys/resource.h>
static int heap_headroom_ok(void) {
    struct rlimit rl;
    if (getrlimit(RLIMIT_AS, &rl) == 0 && rl.rlim_cur != RLIM_INFINITY
        && rl.rlim_cur < (32ull << 20)) return 0;
    return 1;
}

Try / catch

if (veil_nl_connect(&g_ctx) != 0) {
    fprintf(stderr, "veil: bring-up failed (memory?) — restarting via procd\n");
    return 1; /* let the supervisor respawn with thresholds */
}

Prevention

When it happens

Trigger: Memory-constrained target at boot; cgroup/`ulimit -v` caps on the daemon; supervisor restart loops under OOM pressure; ABI-mismatched libnl runtime.

Common situations: Small-RAM OpenWrt devices; zram absent and many services enabled; binaries built against one libnl3 version and run against another.

Related errors


AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16). Data as JSON: /api/errors/d88598c6bc176568. Report an issue: GitHub.