Raw Socket Example with Connect and Bind API

For the below code, to understand the setup requirements, once can check the link below

Raw Socket Example with Connect and Bind API – setup

The below code creates the TCP header and basically resends the same TCP packet over and over again in a “while 1” loop. Run the server side code first and then the client code. 

Raw Socket Server Side CodeRaw Socket Client side code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <errno.h>
#include <linux/ip.h>
#include <netinet/tcp.h>

struct sockaddr_in *servaddr = NULL, *client_addr = NULL;
int sock_fd;

#define PORT 50000
#define PORT_CLIENT 50001
/* structure to calculate TCP checksum
* The below members are part of the IP header
* which do not change from the TCP layer and hence
* are used as a part of the TCP checksum */

struct pseudo_iphdr {
        unsigned int source_ip_addr;
        unsigned int dest_ip_addr;
        unsigned char fixed;
        unsigned char protocol;
        unsigned short tcp_len;
};

/* checksum code to calculate TCP checksum
* Code taken from Unix network programming – Richard stevens*/

unsigned short in_cksum (uint16_t * addr, int len)
{
        int nleft = len;
        unsigned int sum = 0;
        unsigned short *w = addr;
        unsigned short answer = 0;

        /* Our algorithm is simple, using a 32 bit accumulator (sum), we add
        * sequential 16 bit words to it, and at the end, fold back all the
        * carry bits from the top 16 bits into the lower 16 bits.
        */
        while (nleft > 1) {
                sum += *w++;
                nleft -= 2;
        }

        /* mop up an odd byte, if necessary */
        if (nleft == 1) {
                *(unsigned char *) (&answer) = * (unsigned char *) w;
                sum += answer;
        }

        /* add back carry outs from top 16 bits to low 16 bits */
        sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
        sum += (sum >> 16); /* add carry */
        answer = (unsigned short) ~sum; /* truncate to 16 bits */
        return (answer);
}

/* Interrupt_handler – so that CTRL + C can be used to
* exit the program */
void interrupt_handler (int signum) {
        close(sock_fd);
        free(client_addr);
        exit(0);
}

#if DEBUG
/* print the IP and TCP headers */
void dumpmsg(unsigned char *recvbuffer, int length) {
        int count_per_length = 40, i = 0;
        for (i = 0; i < count_per_length; i++) {
                printf(“%02x “, recvbuffer[i]);
        }
        printf(“\n”);
}
#endif

int main () {
        char buffer[1024] = {0};
        unsigned char recvbuffer[1024] = {0};
        int length;
        char *string = “Hello client”;
        struct tcphdr *tcp_hdr = NULL;
        char *string_data = NULL;
        char *recv_string_data = NULL;
        char *csum_buffer = NULL;
        struct pseudo_iphdr csum_hdr;
        int error;

        signal (SIGINT, interrupt_handler);
        signal (SIGTERM, interrupt_handler);

        /* Part 1: create the socket */
        sock_fd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
        if(0 > sock_fd) {
               printf(“unable to create socket\n”);
               exit(0);
        }

        servaddr = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
        if (servaddr == NULL) {
                printf(“could not allocate memory\n”);
                goto end;
        }

        servaddr->sin_family = AF_INET;
        servaddr->sin_port = PORT;
        servaddr->sin_addr.s_addr = inet_addr(“192.168.1.11”);

        /* Part 2 – fill data structure and bind to socket */
        if (0 != (bind(sock_fd, (struct sockaddr *)servaddr, sizeof(struct sockaddr_in)))) {
                printf(“could not bind server socket to address\n”);
                goto end1;
        }

        /* part 3: read and write data */
        client_addr = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
        if (client_addr == NULL) {
                printf(“Unable to allocate memory to client address socket\n”);
                goto end2;
        }

        client_addr->sin_family = AF_INET;
        client_addr->sin_port = PORT_CLIENT;
        client_addr->sin_addr.s_addr = inet_addr(“192.168.1.14”);       

        error = connect(sock_fd, (struct sockaddr *)client_addr, sizeof(struct sockaddr_in));
        if (error != 0) {
                printf(“error %d”, errno);
                printf(“connect returned error\n”);
                goto end2;
        }

        /* copy the data after the TCP header */
        string_data = (char *) (buffer + sizeof(struct tcphdr));
        strncpy(string_data, string, strlen(string));

        /* Modify some parameters to send to client in TCP hdr
        * code will perform a syn burst (flood) to the receive side */

        tcp_hdr = (struct tcphdr *)buffer;
        tcp_hdr->source = htons(PORT);
        tcp_hdr->dest = htons(PORT_CLIENT);
        tcp_hdr->ack_seq = 0x0; /* seq number */
        tcp_hdr->doff = 5; /* data_offset * 4 is TCP header size */
        tcp_hdr->syn = 1; /* SYN flag */
        tcp_hdr->window = htons(200); /* Window size scaling*/

        /* calculate the TCP checksum – based on pseudo IP header + TCP HDR +
        * TCP data. create a buffer to calculate CSUM and calculate CSUM*/

        csum_buffer = (char *)calloc((sizeof(struct pseudo_iphdr) + sizeof(struct tcphdr) + strlen(string_data)), sizeof(char));
        if (csum_buffer == NULL) {
                printf(“Unable to allocate csum buffer\n”);
                goto end1;
        }

        csum_hdr.source_ip_addr = inet_addr(“192.168.1.11”);
        csum_hdr.dest_ip_addr = inet_addr(“192.168.1.14”);
        csum_hdr.fixed = 0;
        csum_hdr.protocol = IPPROTO_TCP; /* TCP protocol */
        csum_hdr.tcp_len = htons(sizeof(struct tcphdr) + strlen(string_data) + 1);

        memcpy(csum_buffer, (char *)&csum_hdr, sizeof(struct pseudo_iphdr));
        memcpy(csum_buffer + sizeof(struct pseudo_iphdr), buffer, (sizeof(struct tcphdr) + strlen(string_data) + 1));

        tcp_hdr->check = (in_cksum((unsigned short *) csum_buffer,
       (sizeof(struct pseudo_iphdr)+ sizeof(struct tcphdr) + strlen(string_data) + 1)));

       printf(“checksum is %x”, tcp_hdr->check);
       /* since we are resending the same packet over and over again
       * free the csum buffer here */
       free (csum_buffer);

       while (1) {
                memset(recvbuffer, 0, sizeof(recvbuffer));

                read(sock_fd, recvbuffer, sizeof(recvbuffer));
                tcp_hdr = (struct tcphdr *)(recvbuffer + sizeof (struct iphdr));
                recv_string_data = (char *) (recvbuffer + sizeof (struct iphdr) + sizeof (struct tcphdr));
#if DEBUG
               dumpmsg((unsigned char *)&recvbuffer, (sizeof(struct iphdr) + sizeof(struct tcphdr)+ strlen(string_data) + 1));
#endif
               if (PORT == ntohs(tcp_hdr->dest)) {
                       printf(“tcp destination is client %d, tcp window is %d\n”,ntohs(tcp_hdr->dest), ntohs(tcp_hdr->window));
                       printf(“data is %s\n”, recv_string_data);
               }

               write(sock_fd, buffer, sizeof(buffer));
        }

end2:
        free(client_addr);
end1:
        free(servaddr);
end:
        close(sock_fd);

        return 0;
}

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <errno.h>
#include <netinet/tcp.h>
#include <linux/ip.h>

struct sockaddr_in *serveraddr = NULL, *clientaddr;
int sockfd;

#define PORT 50001
#define SERVER_PORT 50000

/* structure to calculate TCP checksum
* The below members are part of the IP header
* which do not change from the TCP layer and hence
* are used as a part of the TCP checksum */

struct pseudo_iphdr {
        unsigned int source_ip_addr;
        unsigned int dest_ip_addr;
        unsigned char fixed;
        unsigned char protocol;
        unsigned short tcp_len;
};

/* checksum code to calculate TCP checksum
* Code taken from Unix network programming – Richard stevens*/

unsigned short in_cksum (uint16_t * addr, int len)
{
        int nleft = len;
        unsigned int sum = 0;
        unsigned short *w = addr;
        unsigned short answer = 0;

        /* Our algorithm is simple, using a 32 bit accumulator (sum), we add
        * sequential 16 bit words to it, and at the end, fold back all the
        * carry bits from the top 16 bits into the lower 16 bits.
        */
        while (nleft > 1) {
                sum += *w++;
                nleft -= 2;
        }

        /* mop up an odd byte, if necessary */
        if (nleft == 1) {
                *(unsigned char *) (&answer) = * (unsigned char *) w;
                sum += answer;
        }

        /* add back carry outs from top 16 bits to low 16 bits */
        sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
        sum += (sum >> 16); /* add carry */
        answer = (unsigned short) ~sum; /* truncate to 16 bits */
        return (answer);
}

/* Interrupt_handler – so that CTRL + C can be used to
* exit the program */
void interrupt_handler (int signum) {
        close(sockfd);
        free(clientaddr);
        exit(0);
}

#if DEBUG
/* print the IP and TCP headers */
void dumpmsg(unsigned char *recvbuffer, int length) {
        int count_per_length = 40, i = 0;
        for (i = 0; i < count_per_length; i++) {
                printf(“%02x “, recvbuffer[i]);
        }
        printf(“\n”);
}
#endif

int main () {
        char buffer[1024] = {0};
        unsigned char recvbuffer[1024] = {0};
        int length;
        char *string = “Hello server”;
        struct tcphdr *tcp_hdr = NULL;
        char *string_data = NULL;
        char *recv_string_data = NULL;
        char *csum_buffer = NULL;
        struct pseudo_iphdr csum_hdr;
        int error;

        signal (SIGINT, interrupt_handler);
        signal (SIGTERM, interrupt_handler);

        /* Part 1: create the socket */
        sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
        if(0 > sockfd) {
                printf(“unable to create socket\n”);
                exit(0);
        }

        clientaddr = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
        if (clientaddr == NULL) {
                printf(“could not allocate memory\n”);
                goto end;
        }

        clientaddr->sin_family = AF_INET;
        clientaddr->sin_port = PORT;
        clientaddr->sin_addr.s_addr = inet_addr(“192.168.1.14”);

        /* Part 2 – fill data structure and bind to socket */
        if (0 != (bind(sockfd, (struct sockaddr *)clientaddr, sizeof(struct sockaddr_in)))) {
                printf(“could not bind server socket to address\n”);
                goto end1;
        }

        /* part 3: read and write data */
        serveraddr = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
        if (serveraddr == NULL) {
                printf(“Unable to allocate memory to server address socket\n”);
                goto end2;
        }
        serveraddr->sin_family = AF_INET;
        serveraddr->sin_port = SERVER_PORT;
        serveraddr->sin_addr.s_addr = inet_addr(“192.168.1.11”);

        error = connect(sockfd, (struct sockaddr *)serveraddr, sizeof(struct sockaddr_in));
        if (error != 0) {
                printf(“error %d”, errno);
                printf(“connect returned error\n”);
                goto end2;
        }

        /* copy the data after the TCP header */
        string_data = (char *) (buffer + sizeof(struct tcphdr));
        strncpy(string_data, string, strlen(string));

        /* Modify some parameters to send to client in TCP hdr
        * code will perform a syn burst (flood) to the receive side */

        tcp_hdr = (struct tcphdr *)buffer;
        tcp_hdr->source = htons(PORT);
        tcp_hdr->dest = htons(SERVER_PORT);
        tcp_hdr->ack_seq = 0x0; /* seq number */
        tcp_hdr->doff = 5; /* data_offset * 4 is TCP header size */
        tcp_hdr->syn = 1; /* SYN flag */
        tcp_hdr->window = htons(200); /* Window size scaling*/

        /* calculate the TCP checksum – based on pseudo IP header + TCP HDR +
        * TCP data. create a buffer to calculate CSUM and calculate CSUM*/

        csum_buffer = (char *)calloc((sizeof(struct pseudo_iphdr) + sizeof(struct tcphdr) + strlen(string_data)), sizeof(char));
        if (csum_buffer == NULL) {
                printf(“Unable to allocate csum buffer\n”);
                goto end1;
        }

        csum_hdr.source_ip_addr = inet_addr(“192.168.1.14”);
        csum_hdr.dest_ip_addr = inet_addr(“192.168.1.11”);
        csum_hdr.fixed = 0;
        csum_hdr.protocol = IPPROTO_TCP; /* TCP protocol */
        csum_hdr.tcp_len = htons(sizeof(struct tcphdr) + strlen(string_data) + 1);

        memcpy(csum_buffer, (char *)&csum_hdr, sizeof(struct pseudo_iphdr));
        memcpy(csum_buffer + sizeof(struct pseudo_iphdr), buffer, (sizeof(struct tcphdr) + strlen(string_data) + 1));

        tcp_hdr->check = (in_cksum((unsigned short *) csum_buffer,
(sizeof(struct pseudo_iphdr)+ sizeof(struct tcphdr) + strlen(string_data) + 1)));

        printf(“checksum is %x”, tcp_hdr->check);
        /* since we are resending the same packet over and over again
        * free the csum buffer here */
        free (csum_buffer);

        while (1) {
                 write(sockfd, buffer, sizeof(buffer));

                 memset(recvbuffer, 0, sizeof(recvbuffer));
                 read(sockfd, recvbuffer, sizeof(recvbuffer));
                 tcp_hdr = (struct tcphdr *)(recvbuffer + sizeof (struct iphdr));
                 recv_string_data = (char *) (recvbuffer + sizeof (struct iphdr) + sizeof (struct tcphdr));
#if DEBUG
                 dumpmsg((unsigned char *)&recvbuffer, (sizeof(struct iphdr) + sizeof(struct tcphdr)+ strlen(string_data) + 1));
#endif
                 if (PORT == ntohs(tcp_hdr->dest)) {
                         printf(“tcp destination is client %d, tcp window is %d\n”,ntohs(tcp_hdr->dest), ntohs(tcp_hdr->window));
                         printf(“data is %s\n”, recv_string_data);
                }
        }

end2:
         free(serveraddr);
end1:
        free(clientaddr);
end:
        close(sockfd);

        return 0;
}

Raw Socket Example with Connect and Bind API – UDP Example

Comments

  1. Pingback: Raw Socket Example with Connect and Bind API – setup | Hitch Hiker's Guide to Learning

  2. Pingback: Analysis of Raw socket code with connect and Bind API | Hitch Hiker's Guide to Learning

Leave a Reply

Your email address will not be published. Required fields are marked *