I'm currently trying to create a Linux echo client using only raw sockets. I'm running a normal TCP server on one computer, and on the client side i'm using raw TCP sockets. I'm running Libpcap on my client side to receive packets and reply when packets are received. I have the three way handshake complete and have a established connection between the client and server.
I am able to send my first ACK, and PSH,ACK(packets 3 & 4) with data and receive a reply from the server with the data that I originally sent(packets 5 & 6).
Any ideas how to stop the PSH, ACKs from sending? I've tried sending an ACK but it would not stop sending still. Below is a wireshark capture and some of the code i'm working with.
This is a screenshot of the packets on wireshark Server(192.168.1.81) Client(192.168.1.85): Wireshark capture
Client Raw TCP Wrapper
void send_raw_tcp_packet(int src_port, int dst_port, struct ifreq interface,
char* src_ip, char* dst_ip, int seq, int ack, char *data, int flags) {
struct sockaddr_in sin;
int *ip_flags, *tcp_flags, status, sending_socket;
const int on = 1;
struct tcp_packet packet;
ip_flags = (int *)calloc(4, sizeof(int));
tcp_flags = (int *)calloc(8, sizeof(int));
int payloadlen = 0;
memset(&packet, 0, sizeof(struct tcp_packet));
// IPv4 header
packet.iphdr.ip_hl = IP4_HDRLEN / sizeof(uint32_t); //header length = 5
packet.iphdr.ip_v = 4; //version = 4
packet.iphdr.ip_tos = 0; //TOS
packet.iphdr.ip_len = htons(IP4_HDRLEN + TCP_HDRLEN); //length: IP header + TCP header
packet.iphdr.ip_id = htons(0); //ID
ip_flags[0] = 0; //Zero
ip_flags[1] = 0; //Don't frag
ip_flags[2] = 0; //More frag
ip_flags[3] = 0; //Frag offset
packet.iphdr.ip_off = htons((ip_flags[0] << 15) + (ip_flags[1] << 14) + (ip_flags[2] << 13) + ip_flags[3]);
packet.iphdr.ip_ttl = 255; //TTL
packet.iphdr.ip_p = IPPROTO_TCP; //Protocol
printf("src_ip: %s\n", src_ip);
printf("dst_ip: %s\n", dst_ip);
// Source IPv4 address (32 bits)
if ((status = inet_pton(AF_INET, src_ip, &(packet.iphdr.ip_src))) != 1) {
perror("inet_pton, src_ip");
exit(EXIT_FAILURE);
}
// Destination IPv4 address (32 bits)
if ((status = inet_pton(AF_INET, dst_ip, &(packet.iphdr.ip_dst))) != 1) {
perror("inet_pton, dst_ip");
exit(EXIT_FAILURE);
}
packet.iphdr.ip_sum = 1;
packet.iphdr.ip_sum = checksum((uint16_t *)&packet.iphdr, IP4_HDRLEN);
// TCP header
if (src_port == 0) {
packet.tcphdr.th_sport = generate_rand(65535.0);
} else {
packet.tcphdr.th_sport = src_port;
}
if (dst_port == 0) {
packet.tcphdr.th_dport = generate_rand(65535.0);
} else {
packet.tcphdr.th_dport = htons(dst_port);
}
packet.tcphdr.th_seq = htonl(seq); //SEQ
packet.tcphdr.th_ack = htonl(ack); //ACK - 0 for first packet
packet.tcphdr.th_x2 = 0; //Reserved
packet.tcphdr.th_off = TCP_HDRLEN / 4; //Offset
// Flags (8 bits)
if(flags == PSHACK){
tcp_flags[0] = 0; //FIN
tcp_flags[1] = 0; //SYN
tcp_flags[3] = 1; //PSH
tcp_flags[4] = 1; //ACK
tcp_flags[2] = 0; //RST
}else if(flags == SYNACK){
tcp_flags[0] = 0; //FIN
tcp_flags[1] = 1; //SYN
tcp_flags[3] = 0; //PSH
tcp_flags[4] = 1; //ACK
tcp_flags[2] = 0; //RST
}else if(flags == FINACK){
tcp_flags[0] = 1; //FIN
tcp_flags[1] = 0; //SYN
tcp_flags[3] = 0; //PSH
tcp_flags[4] = 1; //ACK
tcp_flags[2] = 0; //RST
}else if(flags == FIN){
tcp_flags[0] = 1; //FIN
tcp_flags[1] = 0; //SYN
tcp_flags[3] = 0; //PSH
tcp_flags[4] = 0; //ACK
tcp_flags[2] = 0; //RST
} else if(flags == SYN){
tcp_flags[0] = 0; //FIN
tcp_flags[1] = 1; //SYN
tcp_flags[3] = 0; //PSH
tcp_flags[4] = 0; //ACK
tcp_flags[2] = 0; //RST
}else if(flags == ACK){
tcp_flags[0] = 0; //FIN
tcp_flags[1] = 0; //SYN
tcp_flags[3] = 0; //PSH
tcp_flags[4] = 1; //ACK
tcp_flags[2] = 0; //RST
}else if(flags == RST){
tcp_flags[0] = 0; //FIN
tcp_flags[1] = 0; //SYN
tcp_flags[3] = 0; //PSH
tcp_flags[4] = 0; //ACK
tcp_flags[2] = 1; //RST
}
tcp_flags[5] = 0; //URG
tcp_flags[6] = 0; //ECE
tcp_flags[7] = 0; //CWR
packet.tcphdr.th_flags = 0;
for (int i = 0; i < 8; i++) {
packet.tcphdr.th_flags += (tcp_flags[i] << i);
}
packet.tcphdr.th_win = htons(64240); //Window size
packet.tcphdr.th_urp = htons(0); //Urgent Pointer
//memset(packet.payload, 0, sizeof(packet.payload));
if(data != NULL){
sprintf (packet.payload, "%s", data);
payloadlen = strlen(packet.payload);
}
//payloadlen = strlen(packet.payload);
packet.tcphdr.th_sum = tcp4_checksum(packet.iphdr, packet.tcphdr, (uint8_t *) packet.payload, payloadlen);
memset(&sin, 0, sizeof(struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = packet.iphdr.ip_dst.s_addr;
if ((sending_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
perror("socket() failed ");
exit(EXIT_FAILURE);
}
if (setsockopt(sending_socket, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0) {
perror("setsockopt() failed to set IP_HDRINCL ");
exit(EXIT_FAILURE);
}
if (setsockopt(sending_socket, SOL_SOCKET, SO_BINDTODEVICE, &interface,sizeof(interface)) < 0) {
perror("setsockopt() failed to bind to interface ");
exit(EXIT_FAILURE);
}
if (sendto(sending_socket, &packet, IP4_HDRLEN + TCP_HDRLEN + payloadlen, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
perror("sendto() failed ");
exit(EXIT_FAILURE);
}
close(sending_socket);
// Free allocated memory.
free(ip_flags);
free(tcp_flags);
}
Server code
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#define PORT "8045"
#define MAXCONNECTIONS 1024
int main(void){
int sockfd, new_fd,rv, yes =1;
struct addrinfo hints, *servinfo, *p;
struct sockaddr_storage their_addr;
socklen_t sin_size;
struct sigaction sa;
char s[INET6_ADDRSTRLEN];
hints = set_hints(AF_UNSPEC, SOCK_STREAM, AI_PASSIVE);
if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,p->ai_protocol)) == -1) {
perror("server: socket");
continue;
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}
if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("server: bind");
continue;
}
break;
}
freeaddrinfo(servinfo);
if (listen(sockfd, MAXCONNECTIONS) == -1) {
perror("listen");
exit(1);
}
printf("server: waiting for connections...\n");
sin_size = sizeof their_addr;
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
if (new_fd == -1) {
perror("accept");
}
inet_ntop(their_addr.ss_family,get_in_addr((struct sockaddr *)&their_addr), s, sizeof s);
printf("server: got connection from %s\n", s);
while(1) {
char data[1024];
//recv_normal_tcp_packet(new_fd, data, sizeof(data));
int bytes_receieved = recv(new_fd, data, sizeof(data),0);
printf("Received: %s from %s\n",data, s);
send_normal_tcp_packet(new_fd, data, bytes_receieved);
}
close(new_fd);
close(sockfd);
return 0;
}