?
Solved

checksum problem with raw socket

Posted on 2003-03-16
3
Medium Priority
?
628 Views
Last Modified: 2008-01-09
hi all I writing a a nmap like softare in C#.

All works fine except the checkusm on TCP header, checksum on IP header is correct accordint to network sniffer !!
So i send a tcp packet with the SYN flag I dont get any answer because packet is rejected due to its checksum error ...

I dont understand very well why I have to use a pseudoheader structure while buildint TCP packet even if I know TCP checksum is calculated on a part of IP header.

Here is my source code :

##################################
unsigned short in_checksum(u_short * addr, int len)
{
      register int nleft = len;
      register int sum= 0;
      u_short answer=0;
      
      while (nleft >1)
            {
            sum += *addr++;
            nleft -=2;
            }
      
      if (nleft ==1)
            {
            *(u_char *) (&answer) = *(u_char *) addr;
            sum += answer;
            }

      sum = (sum >> 16) + (sum + 0xffff);
        sum += (sum >> 16);
        answer = ~sum;
      return (answer);
}






void connexion (char *cible, int portdest)
{
      struct sockaddr_in destination, from;
      struct iphdr *ip, *iprecu;
        struct tcphdr *tcp, *tcprecu;
       
      struct pseudohdr {
            unsigned long saddr;
            unsigned long daddr;
            char useless;
            unsigned char protocol;
            unsigned short length;
      };

      
      struct pseudohdr pseudo;
      
      
      struct timeval tv_timeout; /*gestion du timeout*/
        char *paquet;
        char *recev_buffer;
      
      int sock, r, retval, nbr;
      
      /* liste de fd utilisee en interne par select */
      fd_set fdsr;      


      int from_len=sizeof(from);
        recev_buffer = malloc(sizeof(struct iphdr) + sizeof(struct tcphdr)) ;
        paquet = malloc(sizeof(struct iphdr) + sizeof(struct tcphdr)) ;
      
      
        ip = (struct iphdr *)paquet;
        tcp = (struct tcphdr *) (paquet + sizeof (struct iphdr));
      /*pseudo = (struct pseudohdr *) (paquet + sizeof(struct iphdr) - sizeof(struct pseudohdr));*/
      
      memset(paquet, 0, sizeof(struct iphdr) + sizeof(struct tcphdr));
      memset(recev_buffer, 0, sizeof(struct iphdr) + sizeof(struct tcphdr));
      

      
      destination.sin_family = AF_INET;
      /*destination.sin_port = htons(portdest);*/ /*on le remplit dans la strcuture*/
      
/*Conversion de la chaine de caractere cible passee en argument a la fonction
en adresse rezo et stockage du resultat dans la structure de connexion*/
      inet_aton (cible, &destination.sin_addr);
      
      if ((sock = socket(PF_INET, SOCK_RAW, IPPROTO_TCP)) <0)
            {
            printf("Erreur a l ouverture de la socket, es tu root ???\n");
            exit(0);
            }      

      /* on veut remplir nous meme l entete IP*/
      if (setsockopt(sock,IPPROTO_IP, IP_HDRINCL, (char *)&r, sizeof(r)) ==-1 )
              {
              printf("error setsockopt\n");
      
      
            }
      /*Remplissage des entetes IP*/

      ip->ihl=5;
      ip->version=4;
      ip->tos=0;
      ip->tot_len= sizeof (struct ip) + sizeof (struct tcphdr);
      ip->id=htons(1);
      ip->frag_off=0;
      ip->ttl=255;
      ip->protocol=IPPROTO_TCP;
      ip->check=0;      /*on met 0 avt de calculer le checksum une fois que le packet sera complet*/
      ip->saddr= inet_addr("10.2.150.5"); /* adresse source , si aucune, le systeme remplis tout seul*/
      ip->daddr= destination.sin_addr.s_addr;
      
      pseudo.saddr= ip->saddr;
      pseudo.daddr= ip->daddr;
      pseudo.useless=0;
      pseudo.protocol = ip->protocol;
      pseudo.length = htons(sizeof(struct tcphdr));
      
      
      /*remplissage de l entete TCP */
      tcp->source = htons(6666);
      tcp->dest = htons(portdest);
      tcp->seq= htons(31337);
      tcp->ack_seq = htons(0);
      tcp->res1 = 0;                  
      tcp->doff = 5;
      tcp->res2 = 0;                  
      tcp->fin = 0;
      tcp->syn= 1;            /* on envoie le flag SYN*/
      tcp->rst = 0;
      tcp->psh = 0;
      tcp->ack = 0;
      tcp->urg = 0;      
      tcp->window = htons(3072);
      tcp->urg_ptr = htons(0);
      tcp->check = in_checksum((u_short *)&pseudo, sizeof(struct tcphdr) + sizeof(struct pseudohdr));
      
      ip->check = in_checksum ((u_short *)ip, sizeof(struct iphdr));

      sendto(sock,paquet, sizeof(struct iphdr) + sizeof(struct tcphdr), 0, (struct sockaddr *)&destination, sizeof(struct sockaddr));
      
      FD_ZERO(&fdsr);
      FD_SET(sock, &fdsr);

      /*timeout sur la fonction select*/
      tv_timeout.tv_sec=2;
      tv_timeout.tv_usec=0;
            
      retval = select (sock+1, &fdsr, NULL, NULL, &tv_timeout);
      
      if (FD_ISSET(sock, &fdsr))
            {
            nbr=recvfrom(sock, recev_buffer,(sizeof(struct iphdr) + sizeof(struct tcphdr)) , 0, (struct sockaddr *)&from, &from_len);
                iprecu = (struct iphdr *)recev_buffer;
                tcprecu = (struct tcphdr *) (recev_buffer + sizeof (struct iphdr));      
            
            if ( tcprecu->syn == 1 && tcprecu->ack == 1)
                  {
                  printf("%d ouvert\t",portdest);
                  }

            else if ( tcprecu->rst == 1)
                  {
                  printf("%d ferme\t",portdest);
                  }

            
      
            /*printf("Reponse de : %s\n", inet_ntoa(*((struct in_addr *)&iprecu->saddr)));
            printf("Valeur de SYN recu : %d\n", tcprecu->syn);
            printf("Valeur de ACK recu : %d\n", tcprecu->ack);
            printf("Valeur de RESET recu : %d\n\n", tcprecu->rst);*/
            
            }

      else  /*si pas de reponse....*/
            {
            printf("service firewalled : %d\n", portdest);
            }
      
close(sock);
free(paquet);
free(recev_buffer);

      
}

############


sorry for my poor english and thanks if someone can spend his time to help me


bye !!

philuxe
0
Comment
Question by:philuxe
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
3 Comments
 

Accepted Solution

by:
qwyjebo earned 200 total points
ID: 8190710
It looks to me as though your problem is this: you have a separate structure declared for the pseudo-header, which you initialize with the appropriate data prior to calculating the tcp checksum. When you calculate the checksum, however, you pass the address of the pseudo-header, and the length of the pseudo-header plus the length of the tcp header. Your structure for the pseudo-header is not adjacent to the tcp header in memory; so basically you are calculating part of the checksum on memory not belonging to the tcp packet. The data included in the pseudo-header, while consisting of fields included in the IP header, does not correspond exactly to the 12 bytes preceeding the TCP header, which I assume you already know since you commented out the following line:

 /*pseudo = (struct pseudohdr *) (paquet + sizeof(struct iphdr) - sizeof(struct pseudohdr));*/

One way to correct this would be to create a new checksum function specific to calculating the tcp checksum, to which you could pass the pseudo-header fields along with the address & length of the tcp segment, and include all in the checksum.
0
 
LVL 20

Expert Comment

by:jmcg
ID: 10102023
No comment has been added lately, so it's time to clean up this TA.
I will leave the following recommendation for this question in the Cleanup topic area:

Accept: qwyjebo {http:#8190710}

Please leave any comments here within the next seven days.
PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

jmcg
EE Cleanup Volunteer
0

Featured Post

NFR key for Veeam Agent for Linux

Veeam is happy to provide a free NFR license for one year.  It allows for the non‑production use and valid for five workstations and two servers. Veeam Agent for Linux is a simple backup tool for your Linux installations, both on‑premises and in the public cloud.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The purpose of this article is to fix the unknown display problem in Linux Mint operating system. After installing the OS if you see Display monitor is not recognized then we can install "MESA" utilities to fix this problem or we can install additio…
The purpose of this article is to demonstrate how we can upgrade Python from version 2.7.6 to Python 2.7.10 on the Linux Mint operating system. I am using an Oracle Virtual Box where I have installed Linux Mint operating system version 17.2. Once yo…
Visualize your data even better in Access queries. Given a date and a value, this lesson shows how to compare that value with the previous value, calculate the difference, and display a circle if the value is the same, an up triangle if it increased…
How to fix incompatible JVM issue while installing Eclipse While installing Eclipse in windows, got one error like above and unable to proceed with the installation. This video describes how to successfully install Eclipse. How to solve incompa…
Suggested Courses

770 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question