#include "packetgen.h"
ushort checksum (unsigned short *addr, int len)
{
unsigned short *w = addr;
int i = len;
int sum = 0;
while (i > 1)
{
sum += *w++;
i-=2;
}
if (i == 1) sum += *(u_char *)w;
sum = (sum >> 16) + (sum & 0xffff);
sum = sum + (sum >> 16);
return (~sum);
}
int send_tcp(pcap_t *raw, unsigned char smac[ETH_ALEN], unsigned char dmac[ETH_ALEN], in_addr_t sip, in_addr_t dip,
unsigned long seq, unsigned long ack, unsigned short win, unsigned char flags,
unsigned short sport, unsigned short dport,
unsigned char* data, unsigned short datalen)
{
char buffer[sizeof(struct ether_header) + sizeof(struct iphdr) + sizeof(struct tcphdr) + datalen];
char pseudo[sizeof(struct pseudoheader) + sizeof(struct tcphdr) + datalen];
struct ether_header *eth;
struct iphdr *iph;
struct tcphdr *tcph;
struct pseudoheader *psh;
eth = (struct ether_header*)buffer;
iph = (struct iphdr*)(buffer+sizeof(struct ether_header));
tcph = (struct tcphdr*)(buffer+sizeof(struct ether_header)+sizeof(struct iphdr));
psh = (struct pseudoheader*)pseudo;
memcpy(buffer+sizeof(struct ether_header)+sizeof(struct iphdr)+sizeof(struct tcphdr), data, datalen);
//ETHERNET HEADER
eth->ether_type = htons(ETH_P_IP);
memcpy(eth->ether_shost, smac, ETH_ALEN);
memcpy(eth->ether_dhost, dmac, ETH_ALEN);
//IP HEADER
iph->ihl = 5;
iph->version = 4;
iph->tos = 0;
iph->tot_len = htons(sizeof(struct iphdr)+sizeof(struct tcphdr)+datalen);
iph->id = htons(1);
iph->frag_off = htons(0);
iph->ttl = 66;
iph->protocol = IPPROTO_TCP;
iph->check = htons(0);
iph->saddr = sip;
iph->daddr = dip;
iph->check = checksum((unsigned short*)iph, sizeof(struct iphdr));
//TCP HEADER
tcph->th_sport = htons(sport);
tcph->th_dport = htons(dport);
tcph->th_seq = htonl(seq);
tcph->th_ack = htonl(ack);
tcph->th_x2 = 0;
tcph->th_off = 5;
tcph->th_flags = flags;
tcph->th_win = htons(win);
tcph->th_sum = 0;
tcph->th_urp = htons(0);
//PSEUDOHEADER
psh->saddr = iph->saddr;
psh->daddr = iph->daddr;
psh->zero = 0;
psh->proto = IPPROTO_TCP;
psh->len = htons(sizeof(struct tcphdr)+datalen);
memcpy(pseudo+sizeof(struct pseudoheader), tcph, sizeof(struct tcphdr));
memcpy(pseudo+sizeof(struct pseudoheader)+sizeof(struct tcphdr), data, datalen);
tcph->th_sum = checksum((unsigned short*)pseudo, sizeof(struct pseudoheader) + sizeof(struct tcphdr) + datalen);
return(pcap_inject(raw, buffer, sizeof(struct ether_header)+sizeof(struct iphdr)+sizeof(struct tcphdr)+datalen)==-1);
}
//To reset a TCP-Packet, we send a RST/ACK packet with SEQ=ACK and ACK=SEQ+1 and WIN=0
void tcp_reset_packet(pcap_t * raw, struct ether_header* eth, struct iphdr* ip, struct tcphdr* tcp)
{
send_tcp(raw, eth->ether_dhost, eth->ether_shost, ip->daddr, ip->saddr,
htonl(tcp->th_ack), htonl(tcp->th_seq)+1, 0,
TH_RST | TH_ACK, htons(tcp->th_dport), htons(tcp->th_sport), 0, 0);
}