DF-3311 / spam.c
/* * spam.c - unprivileged UDP "network peer" packet generator for if_wg. * Sends WireGuard-shaped packets that pass the WG_PKT_IS_* length/type * checks in wg_input() but need no valid crypto (MAC validation happens * later, in the handshake worker): * - 148-byte packets, first word LE 1 (handshake initiation) * - 92-byte packets, first word LE 2 (handshake response) * - 64-byte packets, first word LE 3 (cookie reply) * * usage: spam <ip> <port> <iters> [tag] */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <errno.h> int main(int argc, char **argv) { struct sockaddr_in sin; uint8_t pkt[148]; int s, i, n, sent = 0, errs = 0; unsigned long iter; uint32_t seq = 0; if (argc < 4) { fprintf(stderr, "usage: spam <ip> <port> <iters> [tag]\n"); return 1; } s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { perror("socket"); return 1; } memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons((uint16_t)atoi(argv[2])); if (inet_pton(AF_INET, argv[1], &sin.sin_addr) != 1) { fprintf(stderr, "bad ip\n"); return 1; } iter = strtoul(argv[3], NULL, 0); n = 0; for (; iter == 0 || n < (int)iter; n++) { int len; memset(pkt, (uint8_t)(seq & 0xff), sizeof(pkt)); /* type word: htole32(1|2|3), rest garbage (checked later * by cookie_checker_validate_macs, not by the enqueue path) */ { uint32_t t = (uint32_t)(1 + (seq % 3)); memcpy(pkt, &t, 4); } len = (seq % 3 == 0) ? 148 : ((seq % 3 == 1) ? 92 : 64); *(uint32_t *)(pkt + 4) = seq; seq++; if (sendto(s, pkt, len, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0) { errs++; if (errno == ENOBUFS) usleep(50); } else { sent++; } } fprintf(stderr, "spam[%s]: sent=%d errs=%d\n", argc > 4 ? argv[4] : "-", sent, errs); return 0; } |