DF-0414 / sanity.c
/* * DF-0414 sanity check: a WELL-FORMED PPPoE PADI with ph->length matching * the actual payload should NOT be rejected by the fix. This proves the * fix is precise and doesn't break legitimate PPPoE traffic. */ #include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <netgraph.h> #include <netgraph/ng_message.h> #include <arpa/inet.h> #define ETHERTYPE_PPPOE_DISC 0x8863 #define PADI_CODE 0x09 int main(void) { int cs = -1, ds = -1, rc; NgSetErrLog((void(*)(const char*, ...))printf, (void(*)(const char*, ...))printf); if (NgMkSockNode(NULL, &cs, &ds) < 0) return 2; struct ngm_mkpeer mp; memset(&mp, 0, sizeof(mp)); strlcpy(mp.type, "pppoe", sizeof(mp.type)); strlcpy(mp.ourhook, "mydata", sizeof(mp.ourhook)); strlcpy(mp.peerhook, "ethernet", sizeof(mp.peerhook)); if (NgSendMsg(cs, ".", NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) { fprintf(stderr, "MKPEER: %s\n", strerror(errno)); return 3; } /* Well-formed PADI: eth(14) + pppoe(6) + one SRV_NAME tag (4 bytes empty) * ph->length MUST equal the actual payload = 4 bytes (the tag size). * Total frame = 24 bytes. */ unsigned char frame[24]; memset(frame, 0, sizeof(frame)); memset(frame + 0, 0xff, 6); frame[6]=0x00; frame[7]=0x11; frame[8]=0x22; frame[9]=0x33; frame[10]=0x44; frame[11]=0x55; frame[12] = 0x88; frame[13] = 0x63; frame[14] = 0x11; frame[15] = PADI_CODE; frame[16] = 0x00; frame[17] = 0x00; frame[18] = 0x00; frame[19] = 0x04; /* ph->length = 4 (matches actual) */ frame[20] = 0x01; frame[21] = 0x01; /* tag_type = PTT_SRV_NAME */ frame[22] = 0x00; frame[23] = 0x00; /* tag_len = 0 */ fprintf(stderr, "[*] sending well-formed PADI (ph->length=4, matches payload)\n"); rc = NgSendData(ds, "mydata", frame, sizeof(frame)); if (rc < 0) { fprintf(stderr, "[!] NgSendData failed: %s\n", strerror(errno)); fprintf(stderr, "[!] If this is EMSGSIZE, the fix is INCORRECTLY rejecting valid packets!\n"); return 4; } /* rc==0 means ng_pppoe accepted the frame. ENETUNREACH (no matching service) * would still be propagated, but EMSGSIZE means the fix rejected it. */ fprintf(stderr, "[+] NgSendData returned %d (frame accepted by ng_pppoe)\n", rc); fprintf(stderr, "[+] Fix correctly distinguishes valid ph->length from malicious.\n"); return 0; } |