/*
 * sendtcp.c v0.1 by messer <mssr@gmx.net> (26/05/2003)
 * simple tcp packet generator for win32
 * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * notes:
 * winsock2 required
 * recommended to compile on VC++ .NET
 *
 * run sendtcp.exe without parameters for help
 */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <winsock2.h>
#include <ws2tcpip.h>

#pragma comment(lib,"ws2_32")

struct iphdr {
 UCHAR len:4, ver:4;
 UCHAR tos;
 USHORT tot_len;
 USHORT id;
 USHORT ip_off;
 UCHAR ttl;
 UCHAR proto;
 USHORT sum;
 UINT src_addr;
 UINT dest_addr;
};

struct tcphdr {
 USHORT src_port;
 USHORT dest_port;
 UINT seq;
 UINT ack;
 UCHAR th_x2:4, offset:4;
 UCHAR flags;
 USHORT window;
 USHORT sum;
 USHORT th_urp;
};

struct pseudohdr {
  struct in_addr src_addr;
  struct in_addr dest_addr;
  UCHAR zero;
  UCHAR protocol;
  USHORT length;
} pseudo;

#define IPVER 4
#define DEF_TTL 255
#define DEF_OFFSET 5
#define DEF_WIN 512

#define URG 0x20 // 100000
#define ACK 0x10 // 010000
#define PSH 0x08 // 001000
#define RST 0x04 // 000100
#define SYN 0x02 // 000010
#define FIN 0x01 // 000001

#define SRC_IP "111.111.111.111"
#define SRC_PORT 11

#define PSEUDOSIZE (sizeof(pseudo)+sizeof(struct tcphdr))
#define PACKETSIZE (sizeof(struct iphdr)+sizeof(struct tcphdr))

#define ws_err(function) { printf(function"() failed: %d\n",WSAGetLastError()); exit(1); }
#define err(function) { printf(function"() failed: %d\n",GetLastError()); exit(1); }
#define usage(exename) { printf("\n\
sendtcp 0.1 by messer (26/05/2003)\n\n\
options:\n\
-dip <dest ip>\n\
-dp <dest port>\n\
[-sip <src ip>] default=%s\n\
[-sp <src port>] default=%d\n\
[-ttl <time to live>] default=%d\n\
[-urg -ask -psh -rst -syn- -fin] default=0x00\n\
[-n <number of packets>] default=1\n\n\
example:\n\
%s -dip 153.4.4.4 -dp 34 -ttl 64 -rst -syn -fin -n 56 -sip 134.134.234.134 -sp 666\
", SRC_IP, SRC_PORT, DEF_TTL, exename); exit(0); }

USHORT checksum(USHORT *buffer, int size);
void create_ip(struct iphdr *hdr, struct in_addr srcaddr, struct in_addr destaddr, USHORT id, UCHAR ttl);
void create_tcp(struct tcphdr *hdr, USHORT srcport, USHORT destport, struct in_addr srcaddr, struct in_addr destaddr, UINT seq, UINT ack, UCHAR flags, USHORT win);

void main(int argc, char *args[]) {
	WSADATA wd;
	SOCKET s;
	char packet[PACKETSIZE], tmp1[16];
	struct iphdr *ip;
	struct tcphdr *tcp;
	USHORT src_port=0, dest_port=0;
	struct in_addr src_ip, dest_ip;
	struct sockaddr_in s_in;
	UCHAR ttl=DEF_TTL, flagz=0;
	int i, one = 1, num=1;

	srand((UINT)time(NULL));
	memset(&src_ip,0,sizeof(struct in_addr));
	memset(&dest_ip,0,sizeof(struct in_addr));
	
	for (i=0;i<argc;i++) {
		if (!strcmp(args[i],"-dip"))
			dest_ip.s_addr = inet_addr(args[i+1]);
		if (!strcmp(args[i],"-dp"))
			dest_port = (USHORT)atoi(args[i+1]);
		if (!strcmp(args[i],"-sip"))
			src_ip.s_addr = inet_addr(args[i+1]);
		if (!strcmp(args[i],"-sp"))
			src_port = (USHORT)atoi(args[i+1]);
		if (!strcmp(args[i],"-ttl"))
			ttl = (UCHAR)atoi(args[i+1]);
		if (!strcmp(args[i],"-urg"))
			flagz |= URG;
		if (!strcmp(args[i],"-ack"))
			flagz |= ACK;
		if (!strcmp(args[i],"-psh"))
			flagz |= PSH;
		if (!strcmp(args[i],"-rst"))
			flagz |= RST;
		if (!strcmp(args[i],"-syn"))
			flagz |= SYN;
		if (!strcmp(args[i],"-fin"))
			flagz |= FIN;
		if (!strcmp(args[i],"-n"))
			num = atoi(args[i+1]);
	}

	if (!src_ip.s_addr) src_ip.s_addr = inet_addr(SRC_IP);
	if (!src_port) src_port = (USHORT)SRC_PORT;

	if ((!dest_ip.s_addr) || (!dest_port)) usage(args[0]);

	if (WSAStartup(MAKEWORD(2,2),&wd)) ws_err("WSAStartup");
	if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == SOCKET_ERROR) ws_err("socket");
	if (setsockopt(s,IPPROTO_IP,IP_HDRINCL,(char*)&one,sizeof(one)) == SOCKET_ERROR) ws_err("setsockopt");

	ip = (struct iphdr *)packet;
	tcp = (struct tcphdr *)(packet+sizeof(struct iphdr));

	memset(&s_in,0,sizeof(s_in));
	s_in.sin_family = AF_INET;
	s_in.sin_addr = dest_ip;
	s_in.sin_port = htons(dest_port);

	strncpy(tmp1,inet_ntoa(src_ip),sizeof(tmp1));
	printf("               From                 To              TTL      Flags(hex)\n");
	for (i=0;i<num;i++) {
		create_ip(ip, src_ip, dest_ip, rand(),ttl);
		create_tcp(tcp, src_port, dest_port, src_ip, dest_ip, rand(), rand(), flagz, DEF_WIN);
		if (sendto(s,packet,sizeof(packet),0,(struct sockaddr *)&s_in,sizeof(s_in)) == SOCKET_ERROR) ws_err("sendto");
		printf("[->] %16s:%4d %16s:%4d %6d %10X\n",tmp1,src_port,inet_ntoa(dest_ip),dest_port,ttl,flagz);
	}
	closesocket(s);
	WSACleanup();

}

USHORT checksum(USHORT *buffer, int size) {
	ULONG cksum=0;
	while (size > 1) {
		cksum += *buffer++;
        size  -= sizeof(USHORT);
	}
    if (size) cksum += *(UCHAR *)buffer;   
    cksum = (cksum >> 16) + (cksum & 0xffff);
    cksum += (cksum >>16); 
	return (USHORT)(~cksum); 
}

void create_ip(struct iphdr *hdr, struct in_addr srcaddr, struct in_addr destaddr, USHORT id, UCHAR ttl) {
	memset(hdr,0,sizeof(struct iphdr));
	hdr->ver = IPVER;
	hdr->len = 5;
	hdr->tot_len = htons(PACKETSIZE);
	hdr->id = htons(id);
	hdr->ttl = ttl;
	hdr->proto = IPPROTO_TCP;
	hdr->src_addr = srcaddr.s_addr;
	hdr->dest_addr = destaddr.s_addr;
	hdr->sum = 0;
}

void create_tcp(struct tcphdr *hdr, USHORT srcport, USHORT destport, struct in_addr srcaddr, struct in_addr destaddr, UINT seq, UINT ack, UCHAR flags, USHORT win) {
	char *pseudo_packet;
	memset(hdr,0,sizeof(struct tcphdr));
	hdr->src_port = htons(srcport);
	hdr->dest_port = htons(destport);
	hdr->seq = htonl(seq);
	hdr->ack = htonl(ack);
	hdr->offset = DEF_OFFSET;
	hdr->window = htons(win);
	hdr->flags = flags;

	pseudo.src_addr = srcaddr;
	pseudo.dest_addr = destaddr;
	pseudo.zero = 0;
	pseudo.protocol = IPPROTO_TCP;
	pseudo.length = htons(sizeof(struct tcphdr));

	if ((pseudo_packet = (char *)malloc(PSEUDOSIZE)) == NULL) err("malloc");
	memcpy(pseudo_packet, &pseudo, sizeof(pseudo));
	memcpy(pseudo_packet+sizeof(pseudo), hdr, sizeof(struct tcphdr));

	hdr->sum = (USHORT)checksum((USHORT *)pseudo_packet, PSEUDOSIZE);
	free(pseudo_packet);
}
