DF-3379 / trigger_df3379.c
/* * DF-3379 trigger: configure pfsync0 the way an HA deployment would * (syncdev=lo0 plus a UNICAST sync peer 10.0.2.2), so that a working * pfsync engine would serialize every pf state change and emit proto-240 * packets to 10.0.2.2 within the 1-second pfsync tick. * * On DragonFly the engine is dead: the global `pfsyncif` is never * assigned (only `struct pfsync_softc *pfsyncif = NULL;` at * sys/net/pf/if_pfsync.c:90 -- pfsync_clone_create never does * `pfsyncif = sc`), so pfsync_pack_state()/pfsync_request_update()/ * pfsync_clear_states() all take their `sc == NULL` early-out and no * packet is ever built or sent, no matter how many states exist. * * The unicast peer matters: with the default multicast peer and no * listener, pfsync_pack_state() would early-out anyway (if_pfsync.c:1294); * with syncdev + unicast peer configured, the only thing that can stop * transmission is the dead engine itself. * * Build: cc -o trigger_df3379 trigger_df3379.c * Run: ./trigger_df3379 (then create pf states and watch for proto 240) */ #include <sys/socket.h> #include <sys/ioctl.h> #include <net/if.h> #include <netinet/in.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <err.h> struct pfsyncreq { char pfsyncr_syncdev[IFNAMSIZ]; struct in_addr pfsyncr_syncpeer; int pfsyncr_maxupdates; int pfsyncr_authlevel; }; #define SIOCSETPFSYNC _IOW('i', 247, struct ifreq) #define SIOCGETPFSYNC _IOWR('i', 248, struct ifreq) int main(void) { struct ifreq ifr; struct pfsyncreq preq; int s; s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) err(1, "socket"); memset(&ifr, 0, sizeof(ifr)); memset(&preq, 0, sizeof(preq)); strlcpy(ifr.ifr_name, "pfsync0", sizeof(ifr.ifr_name)); strlcpy(preq.pfsyncr_syncdev, "lo0", sizeof(preq.pfsyncr_syncdev)); inet_pton(AF_INET, "10.0.2.2", &preq.pfsyncr_syncpeer); preq.pfsyncr_maxupdates = 128; ifr.ifr_data = (caddr_t)&preq; printf("[*] SIOCSETPFSYNC(syncdev=lo0, syncpeer=10.0.2.2, maxupd=128)\n"); if (ioctl(s, SIOCSETPFSYNC, &ifr) < 0) err(1, "SIOCSETPFSYNC"); printf("[+] pfsync0 configured; a live engine would now sync every pf state to 10.0.2.2\n"); memset(&ifr, 0, sizeof(ifr)); memset(&preq, 0, sizeof(preq)); strlcpy(ifr.ifr_name, "pfsync0", sizeof(ifr.ifr_name)); ifr.ifr_data = (caddr_t)&preq; if (ioctl(s, SIOCGETPFSYNC, &ifr) == 0) printf("[+] SIOCGETPFSYNC: syncdev=%s maxupd=%d\n", preq.pfsyncr_syncdev, preq.pfsyncr_maxupdates); close(s); return (0); } |