Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 643
  • Last Modified:

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");

      /* 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->tot_len= sizeof (struct ip) + sizeof (struct tcphdr);
      ip->check=0;      /*on met 0 avt de calculer le checksum une fois que le packet sera complet*/
      ip->saddr= inet_addr(""); /* 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.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_SET(sock, &fdsr);

      /*timeout sur la fonction select*/
      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);



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

bye !!

1 Solution
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.
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.

EE Cleanup Volunteer

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now