/*
 * This code is GPL.
 */

#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <linux/netfilter.h>
#include <libipq.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>

/* packet data (65535) + packet length (5) + safety(1) */
#define BUFSIZE 65541

void raw_send(unsigned char *buf, int len)
{

	/* Create a raw socket */
	int s = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);

	if (s == -1) {
		perror("Failed to create socket");
		exit(1);
	}

	/* IP header */
	struct iphdr *iph = (struct iphdr *)buf;

	/* TCP header */
	struct tcphdr *tcph = (struct tcphdr *)(buf + sizeof(struct ip));

	/* Destination address resolution */
	struct sockaddr_in sin;
	sin.sin_family = AF_INET;
	sin.sin_port = tcph->dest;
	sin.sin_addr.s_addr = iph->daddr;

	/* Tell to the kernel that headers are included in the packet */
	int one = 1;
	const int *val = &one;

	if (setsockopt(s, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0) {
		perror("Error setting IP_HDRINCL");
		exit(0);
	}

	/* Send the packet */
	if (sendto(s, buf, len, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)
		perror("sendto failed");
	else
		printf("Packet Send. Length : %d \n", len);

	close(s);
}

int get_char()
{
	int buf[1];
	ssize_t ret;

	ret = read(0, (void *)buf, 1);
	if (ret == -1) {
		perror("Error! read()");
		exit(EXIT_FAILURE);
	}
	if (ret == 0) {
		return EOF;
	}

	return *buf;
}

int get_len()
{
	int i, ch, factor, len;

	factor = 10000;
	len = 0;
	for (i = 0; i < 5; i++) {
		ch = get_char();
		ch = (unsigned char)ch - 48;
		len += (ch * factor);
		factor /= 10;
	}
	if (len < 0 || len > 65535) {
		printf("Packet length Error: %d", len);
		exit(EXIT_FAILURE);
	}

	return len;
}

void get_data()
{
	int i, len;
	unsigned char buf[BUFSIZE] = { 0 };

	len = get_len();

	for (i = 0; i < len; i++)
		buf[i] = get_char();

	raw_send(buf, len);
}

int main(void)
{
	while (1)
		get_data();
	return 0;
}