Skip to content

Instantly share code, notes, and snippets.

@Chion82
Created February 12, 2017 14:56
Show Gist options
  • Save Chion82/699ae432a27507242ea788df324f4e47 to your computer and use it in GitHub Desktop.
Save Chion82/699ae432a27507242ea788df324f4e47 to your computer and use it in GitHub Desktop.
fake TCP test
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <string.h>
#include "trans_packet.h"
void on_packet_recv(char* from_ip, uint16_t from_port, char* payload, int size, unsigned int seq) {
printf("Packet received from=%s:%d, seq=%d\n", from_ip, from_port, seq);
char* message = (char*)malloc(size);
memcpy(message, payload, size);
printf(message);
free(message);
printf("\n");
}
int main (void) {
init_packet();
struct packet_info packetinfo;
packetinfo.dest_ip = "108.0.0.1"; //填写服务器IP
packetinfo.dest_port = 8888;
packetinfo.source_ip = "192.168.1.100"; //本地IP
packetinfo.source_port = 34567;
packetinfo.on_packet_recv = on_packet_recv;
char* text = "Hello World!";
send_packet(&packetinfo, text, strlen(text) + 1, 1234);
recv_packet_loop(&packetinfo);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <string.h>
#include "trans_packet.h"
struct packet_info packetinfo;
void on_packet_recv(char* from_ip, uint16_t from_port, char* payload, int size, unsigned int seq) {
printf("Packet received from=%s:%d, seq=%d\n", from_ip, from_port, seq);
char* message = (char*)malloc(size);
memcpy(message, payload, size);
printf(message);
free(message);
printf("\n");
packetinfo.dest_ip = from_ip;
packetinfo.dest_port = from_port;
char* text = "Response from server.";
send_packet(&packetinfo, text, strlen(text) + 1, 5678);
}
int main (void) {
init_packet();
packetinfo.dest_ip = 0;
packetinfo.dest_port = 0;
packetinfo.source_ip = "108.0.0.1"; //填写服务器IP
packetinfo.source_port = 8888;
packetinfo.on_packet_recv = on_packet_recv;
recv_packet_loop(&packetinfo);
return 0;
}
#include <stdio.h> //for printf
#include <string.h> //memset
#include <sys/socket.h> //for socket ofcourse
#include <stdlib.h> //for exit(0);
#include <errno.h> //For errno - the error number
#include <netinet/tcp.h> //Provides declarations for tcp header
#include <netinet/ip.h> //Provides declarations for ip header
#include <netinet/if_ether.h>
#include <arpa/inet.h>
#include "trans_packet.h"
/*
96 bit (12 bytes) pseudo header needed for tcp header checksum calculation
*/
struct pseudo_header {
u_int32_t source_address;
u_int32_t dest_address;
u_int8_t placeholder;
u_int8_t protocol;
u_int16_t tcp_length;
};
unsigned short csum(unsigned short *ptr,int nbytes);
int packet_send_sd;
int packet_recv_sd;
void init_packet() {
packet_send_sd = socket(AF_INET , SOCK_RAW , IPPROTO_TCP);
packet_recv_sd = socket(AF_PACKET , SOCK_DGRAM , htons(ETH_P_ALL));
if(packet_send_sd == -1 || packet_recv_sd == -1) {
//socket creation failed, may be because of non-root privileges
perror("Failed to create socket");
exit(1);
}
//IP_HDRINCL to tell the kernel that headers are included in the packet
int one = 1;
const int *val = &one;
if (setsockopt (packet_send_sd, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0) {
perror("Error setting IP_HDRINCL");
exit(2);
}
}
void recv_packet_loop(struct packet_info* packetinfo) {
int saddr_size , size;
struct sockaddr saddr;
unsigned short iphdrlen;
struct in_addr from_addr;
char buffer[MTU];
while(1) {
saddr_size = sizeof(saddr);
//Receive a packet
size = recvfrom(packet_recv_sd, buffer, MTU, 0 ,&saddr , &saddr_size);
if(size <0 ) {
printf("Recvfrom error , failed to get packets\n");
return;
}
//Now process the packet
struct iphdr *iph = (struct iphdr *)buffer;
iphdrlen =iph->ihl*4;
if (iph->protocol != IPPROTO_TCP) {
continue;
}
struct tcphdr *tcph=(struct tcphdr*)(buffer + iphdrlen);
if (ntohs(tcph->dest) != packetinfo->source_port) {
continue;
}
from_addr.s_addr = iph->saddr;
(*(packetinfo->on_packet_recv))(inet_ntoa(from_addr), ntohs(tcph->source), buffer + iphdrlen + tcph->doff*4, size - tcph->doff*4 - iphdrlen, tcph->seq);
}
}
int send_packet(struct packet_info* packetinfo, char* payload, int payloadlen, unsigned int seq) {
//Datagram to represent the packet
char datagram[MTU], *data , *pseudogram;
if (payloadlen > MTU - 40) {
return -1;
}
//zero out the packet buffer
memset (datagram, 0, MTU);
//IP header
struct iphdr *iph = (struct iphdr *) datagram;
//TCP header
struct tcphdr *tcph = (struct tcphdr *) (datagram + sizeof (struct ip));
struct sockaddr_in sin;
struct pseudo_header psh;
//Data part
data = datagram + sizeof(struct iphdr) + sizeof(struct tcphdr);
memcpy(data , payload, payloadlen);
//some address resolution
sin.sin_family = AF_INET;
sin.sin_port = htons(packetinfo->dest_port);
sin.sin_addr.s_addr = inet_addr (packetinfo->dest_ip);
//Fill in the IP Header
iph->ihl = 5;
iph->version = 4;
iph->tos = 0;
iph->tot_len = sizeof (struct iphdr) + sizeof (struct tcphdr) + payloadlen;
iph->id = htonl (54321); //Id of this packet
iph->frag_off = 0;
iph->ttl = 255;
iph->protocol = IPPROTO_TCP;
iph->check = 0; //Set to 0 before calculating checksum
iph->saddr = inet_addr(packetinfo->source_ip); //Spoof the source ip address
iph->daddr = sin.sin_addr.s_addr;
//TCP Header
tcph->source = htons(packetinfo->source_port);
tcph->dest = sin.sin_port;
tcph->seq = seq;
tcph->ack_seq = 0;
tcph->doff = 5; //tcp header size
tcph->fin=0;
tcph->syn=1;
tcph->rst=0;
tcph->psh=0;
tcph->ack=0;
tcph->urg=0;
tcph->window = htons (5840); /* maximum allowed window size */
tcph->check = 0; //leave checksum 0 now, filled later by pseudo header
tcph->urg_ptr = 0;
//Now the TCP checksum
psh.source_address = inet_addr(packetinfo->source_ip);
psh.dest_address = sin.sin_addr.s_addr;
psh.placeholder = 0;
psh.protocol = IPPROTO_TCP;
psh.tcp_length = htons(sizeof(struct tcphdr) + payloadlen );
int psize = sizeof(struct pseudo_header) + sizeof(struct tcphdr) + payloadlen;
pseudogram = malloc(psize);
memcpy(pseudogram , (char*) &psh , sizeof (struct pseudo_header));
memcpy(pseudogram + sizeof(struct pseudo_header) , tcph , sizeof(struct tcphdr) + payloadlen);
tcph->check = csum( (unsigned short*) pseudogram , psize);
//Ip checksum
iph->check = csum ((unsigned short *) datagram, iph->tot_len);
free(pseudogram);
return sendto (packet_send_sd, datagram, iph->tot_len , 0, (struct sockaddr *) &sin, sizeof (sin));
}
/*
Generic checksum calculation function
*/
unsigned short csum(unsigned short *ptr,int nbytes) {
register long sum;
unsigned short oddbyte;
register short answer;
sum=0;
while(nbytes>1) {
sum+=*ptr++;
nbytes-=2;
}
if(nbytes==1) {
oddbyte=0;
*((u_char*)&oddbyte)=*(u_char*)ptr;
sum+=oddbyte;
}
sum = (sum>>16)+(sum & 0xffff);
sum = sum + (sum>>16);
answer=(short)~sum;
return(answer);
}
#define MTU 1440
struct packet_info {
char* dest_ip;
char* source_ip;
uint16_t dest_port;
uint16_t source_port;
void (*on_packet_recv)(char*, uint16_t, char*, int, unsigned int);
};
void init_packet();
int send_packet(struct packet_info* packetinfo, char* payload, int payloadlen, unsigned int seq);
void recv_packet_loop(struct packet_info* packetinfo);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment