Blame bootstrap_ver/utils/nfsynproxy.c

Packit Service 2cd632
/*
Packit Service 2cd632
 * Copyright (c) 2013 Patrick McHardy <kaber@trash.net>
Packit Service 2cd632
 *
Packit Service 2cd632
 * This program is free software; you can redistribute it and/or modify
Packit Service 2cd632
 * it under the terms of the GNU General Public License version 2 as
Packit Service 2cd632
 * published by the Free Software Foundation.
Packit Service 2cd632
 */
Packit Service 2cd632
Packit Service 2cd632
#define _GNU_SOURCE
Packit Service 2cd632
#include <stdlib.h>
Packit Service 2cd632
#include <stdbool.h>
Packit Service 2cd632
#include <unistd.h>
Packit Service 2cd632
#include <string.h>
Packit Service 2cd632
#include <errno.h>
Packit Service 2cd632
#include <getopt.h>
Packit Service 2cd632
#include <sys/types.h>
Packit Service 2cd632
#include <sys/socket.h>
Packit Service 2cd632
#include <netinet/in.h>
Packit Service 2cd632
#include <arpa/inet.h>
Packit Service 2cd632
#include <pcap/pcap.h>
Packit Service 2cd632
#include <netinet/ip.h>
Packit Service 2cd632
#include <netinet/tcp.h>
Packit Service 2cd632
Packit Service 2cd632
static const char *iface = "lo";
Packit Service 2cd632
static uint16_t port;
Packit Service 2cd632
static const char *chain = "SYNPROXY";
Packit Service 2cd632
Packit Service 2cd632
static int parse_packet(const char *host, const uint8_t *data)
Packit Service 2cd632
{
Packit Service 2cd632
	const struct iphdr *iph = (void *)data + 14;
Packit Service 2cd632
	const struct tcphdr *th = (void *)iph + iph->ihl * 4;
Packit Service 2cd632
	int length;
Packit Service 2cd632
	uint8_t *ptr;
Packit Service 2cd632
Packit Service 2cd632
	if (!th->syn || !th->ack)
Packit Service 2cd632
		return 0;
Packit Service 2cd632
Packit Service 2cd632
	printf("-A %s -d %s -p tcp --dport %u "
Packit Service 2cd632
	       "-m state --state UNTRACKED,INVALID "
Packit Service 2cd632
	       "-j SYNPROXY ", chain, host, port);
Packit Service 2cd632
Packit Service 2cd632
	/* ECE && !CWR */
Packit Service 2cd632
	if (th->res2 == 0x1)
Packit Service 2cd632
		printf("--ecn ");
Packit Service 2cd632
Packit Service 2cd632
	length = th->doff * 4 - sizeof(*th);
Packit Service 2cd632
	ptr = (uint8_t *)(th + 1);
Packit Service 2cd632
	while (length > 0) {
Packit Service 2cd632
		int opcode = *ptr++;
Packit Service 2cd632
		int opsize;
Packit Service 2cd632
Packit Service 2cd632
		switch (opcode) {
Packit Service 2cd632
		case TCPOPT_EOL:
Packit Service 2cd632
			return 1;
Packit Service 2cd632
		case TCPOPT_NOP:
Packit Service 2cd632
			length--;
Packit Service 2cd632
			continue;
Packit Service 2cd632
		default:
Packit Service 2cd632
			opsize = *ptr++;
Packit Service 2cd632
			if (opsize < 2)
Packit Service 2cd632
				return 1;
Packit Service 2cd632
			if (opsize > length)
Packit Service 2cd632
				return 1;
Packit Service 2cd632
Packit Service 2cd632
			switch (opcode) {
Packit Service 2cd632
			case TCPOPT_MAXSEG:
Packit Service 2cd632
				if (opsize == TCPOLEN_MAXSEG)
Packit Service 2cd632
					printf("--mss %u ", ntohs(*(uint16_t *)ptr));
Packit Service 2cd632
				break;
Packit Service 2cd632
			case TCPOPT_WINDOW:
Packit Service 2cd632
				if (opsize == TCPOLEN_WINDOW)
Packit Service 2cd632
					printf("--wscale %u ", *ptr);
Packit Service 2cd632
				break;
Packit Service 2cd632
			case TCPOPT_TIMESTAMP:
Packit Service 2cd632
				if (opsize == TCPOLEN_TIMESTAMP)
Packit Service 2cd632
					printf("--timestamp ");
Packit Service 2cd632
				break;
Packit Service 2cd632
			case TCPOPT_SACK_PERMITTED:
Packit Service 2cd632
				if (opsize == TCPOLEN_SACK_PERMITTED)
Packit Service 2cd632
					printf("--sack-perm ");
Packit Service 2cd632
				break;
Packit Service 2cd632
			}
Packit Service 2cd632
Packit Service 2cd632
			ptr += opsize - 2;
Packit Service 2cd632
			length -= opsize;
Packit Service 2cd632
		}
Packit Service 2cd632
	}
Packit Service 2cd632
	printf("\n");
Packit Service 2cd632
	return 1;
Packit Service 2cd632
}
Packit Service 2cd632
Packit Service 2cd632
static void probe_host(const char *host)
Packit Service 2cd632
{
Packit Service 2cd632
	struct sockaddr_in sin;
Packit Service 2cd632
	char pcap_errbuf[PCAP_ERRBUF_SIZE];
Packit Service 2cd632
	struct pcap_pkthdr pkthdr;
Packit Service 2cd632
	const uint8_t *data;
Packit Service 2cd632
	struct bpf_program fp;
Packit Service 2cd632
	pcap_t *ph;
Packit Service 2cd632
	int fd;
Packit Service 2cd632
Packit Service 2cd632
	ph = pcap_create(iface, pcap_errbuf);
Packit Service 2cd632
	if (ph == NULL) {
Packit Service 2cd632
		perror("pcap_create");
Packit Service 2cd632
		goto err1;
Packit Service 2cd632
	}
Packit Service 2cd632
Packit Service 2cd632
	if (pcap_setnonblock(ph, 1, pcap_errbuf) == -1) {
Packit Service 2cd632
		perror("pcap_setnonblock");
Packit Service 2cd632
		goto err2;
Packit Service 2cd632
	}
Packit Service 2cd632
Packit Service 2cd632
	if (pcap_setfilter(ph, &fp) == -1) {
Packit Service 2cd632
		pcap_perror(ph, "pcap_setfilter");
Packit Service 2cd632
		goto err2;
Packit Service 2cd632
	}
Packit Service 2cd632
Packit Service 2cd632
	if (pcap_activate(ph) != 0) {
Packit Service 2cd632
		pcap_perror(ph, "pcap_activate");
Packit Service 2cd632
		goto err2;
Packit Service 2cd632
	}
Packit Service 2cd632
Packit Service 2cd632
	if (pcap_compile(ph, &fp, "src host 127.0.0.1 and tcp and src port 80",
Packit Service 2cd632
			 1, PCAP_NETMASK_UNKNOWN) == -1) {
Packit Service 2cd632
		pcap_perror(ph, "pcap_compile");
Packit Service 2cd632
		goto err2;
Packit Service 2cd632
	}
Packit Service 2cd632
Packit Service 2cd632
	fd = socket(AF_INET, SOCK_STREAM, 0);
Packit Service 2cd632
	if (fd < 0) {
Packit Service 2cd632
		perror("socket");
Packit Service 2cd632
		goto err3;
Packit Service 2cd632
	}
Packit Service 2cd632
Packit Service 2cd632
	memset(&sin, 0, sizeof(sin));
Packit Service 2cd632
	sin.sin_family		= AF_INET;
Packit Service 2cd632
	sin.sin_port		= htons(port);
Packit Service 2cd632
	sin.sin_addr.s_addr	= inet_addr(host);
Packit Service 2cd632
Packit Service 2cd632
	if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
Packit Service 2cd632
		perror("connect");
Packit Service 2cd632
		goto err4;
Packit Service 2cd632
	}
Packit Service 2cd632
Packit Service 2cd632
	for (;;) {
Packit Service 2cd632
		data = pcap_next(ph, &pkthdr);
Packit Service 2cd632
		if (data == NULL)
Packit Service 2cd632
			break;
Packit Service 2cd632
		if (parse_packet(host, data))
Packit Service 2cd632
			break;
Packit Service 2cd632
	}
Packit Service 2cd632
Packit Service 2cd632
	close(fd);
Packit Service 2cd632
Packit Service 2cd632
err4:
Packit Service 2cd632
	close(fd);
Packit Service 2cd632
err3:
Packit Service 2cd632
	pcap_freecode(&fp);
Packit Service 2cd632
err2:
Packit Service 2cd632
	pcap_close(ph);
Packit Service 2cd632
err1:
Packit Service 2cd632
	return;
Packit Service 2cd632
}
Packit Service 2cd632
Packit Service 2cd632
enum {
Packit Service 2cd632
	OPT_HELP	= 'h',
Packit Service 2cd632
	OPT_IFACE	= 'i',
Packit Service 2cd632
	OPT_PORT	= 'p',
Packit Service 2cd632
	OPT_CHAIN	= 'c',
Packit Service 2cd632
};
Packit Service 2cd632
Packit Service 2cd632
static const struct option options[] = {
Packit Service 2cd632
	{ .name = "help",  .has_arg = false, .val = OPT_HELP },
Packit Service 2cd632
	{ .name = "iface", .has_arg = true,  .val = OPT_IFACE },
Packit Service 2cd632
	{ .name = "port" , .has_arg = true,  .val = OPT_PORT },
Packit Service 2cd632
	{ .name = "chain", .has_arg = true,  .val = OPT_CHAIN },
Packit Service 2cd632
	{ }
Packit Service 2cd632
};
Packit Service 2cd632
Packit Service 2cd632
static void print_help(const char *name)
Packit Service 2cd632
{
Packit Service 2cd632
	printf("%s [ options ] address...\n"
Packit Service 2cd632
	       "\n"
Packit Service 2cd632
	       "Options:\n"
Packit Service 2cd632
	       " -i/--iface        Outbound interface\n"
Packit Service 2cd632
	       " -p/--port         Port number to probe\n"
Packit Service 2cd632
	       " -c/--chain        Chain name to use for rules\n"
Packit Service 2cd632
	       " -h/--help         Show this help\n",
Packit Service 2cd632
	       name);
Packit Service 2cd632
}
Packit Service 2cd632
Packit Service 2cd632
int main(int argc, char **argv)
Packit Service 2cd632
{
Packit Service 2cd632
	int optidx = 0, c;
Packit Service 2cd632
Packit Service 2cd632
	for (;;) {
Packit Service 2cd632
		c = getopt_long(argc, argv, "hi:p:c:", options, &optidx);
Packit Service 2cd632
		if (c == -1)
Packit Service 2cd632
			break;
Packit Service 2cd632
Packit Service 2cd632
		switch (c) {
Packit Service 2cd632
		case OPT_IFACE:
Packit Service 2cd632
			iface = optarg;
Packit Service 2cd632
			break;
Packit Service 2cd632
		case OPT_PORT:
Packit Service 2cd632
			port = atoi(optarg);
Packit Service 2cd632
			break;
Packit Service 2cd632
		case OPT_CHAIN:
Packit Service 2cd632
			chain = optarg;
Packit Service 2cd632
			break;
Packit Service 2cd632
		case OPT_HELP:
Packit Service 2cd632
			print_help(argv[0]);
Packit Service 2cd632
			exit(0);
Packit Service 2cd632
		case '?':
Packit Service 2cd632
			print_help(argv[0]);
Packit Service 2cd632
			exit(1);
Packit Service 2cd632
		}
Packit Service 2cd632
	}
Packit Service 2cd632
Packit Service 2cd632
	argc -= optind;
Packit Service 2cd632
	argv += optind;
Packit Service 2cd632
Packit Service 2cd632
	while (argc > 0) {
Packit Service 2cd632
		probe_host(*argv);
Packit Service 2cd632
		argc--;
Packit Service 2cd632
		argv++;
Packit Service 2cd632
	}
Packit Service 2cd632
	return 0;
Packit Service 2cd632
}