checksum problem with raw socket

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
philuxeAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

qwyjeboCommented:
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
jmcgOwnerCommented:
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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Linux OS Dev

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.