raw sockets und checksums



  • hello,
    I have started to code with raw sockets under win2k. I have succesfully construct
    a ack-packet with the correct checksums, but if i construct a packet with a payload, the checksum is always incorrect( i have examined this with ethereal).

    please take a lock at the following sourcecodes.

    --------------------------head.h-----------------------------------------------

    #include <winsock2.h>
    #include <windows.h>
    #include <ws2tcpip.h>
    #include <stdio.h>
    
    unsigned short checksum(unsigned short *addr, int len);
    struct tcpheader {
     unsigned short int th_sport;
     unsigned short int th_dport;
     unsigned int th_seq;
     unsigned int th_ack;
     unsigned char th_x2:4, th_off:4;
     unsigned char th_flags;
     unsigned short int th_win;
     unsigned short int th_sum;
     unsigned short int th_urp;
    }; /* total tcp header length: 20 bytes (=160 bits) */
    
    struct ipheader {
     unsigned char ip_hl:4, ip_v:4; /* this means that each member is 4 bits */
     unsigned char ip_tos;
     unsigned short int ip_len;
     unsigned short int ip_id;
     unsigned short int ip_off;
     unsigned char ip_ttl;
     unsigned char ip_p;
     unsigned short int ip_sum;
     unsigned int ip_src;
     unsigned int ip_dst;
    }; /* total ip header length: 20 bytes (=160 bits) */
    
    // Psuedo Header
    
    struct body
    {
    
        unsigned  char data [40];
    
    };
    
    struct ps_hdr
    {
        unsigned int   source_address;   // Source Address =>  4 Bytes
        unsigned int   dest_address;     // Destination Address =>  4 Bytes
        unsigned char  placeholder;     // Place Holder =>  1 Bytes
        unsigned char  protocol;     // Protocol =>  1 Bytes
        unsigned short tcp_length;     // TCP Length =>    +  2 Bytes
    
        struct tcpheader tcp;
        struct body data;
    
    };
    

    ---------------------------------EOF-----------------------------------------

    --------------------------------main.cpp-----------------------------------

    #include "head.h"
    
    #define PORT 25
    
    int main (void)
    {
    
    WSADATA wsd;
    char *datagram="";
    int bOpt = 1;
    char info[30] ="das ist ein test";
    
        if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
        {
       printf("WSAStartup() failed: %d\n", GetLastError());
       return -1;
        }
    
    // Create a raw socket
    
        SOCKET s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
        if (s == INVALID_SOCKET)
        {
           printf("WSASocket() failed: %d\n", WSAGetLastError());
           return -1;
        }
    
        struct ipheader *iph = (struct ipheader *) malloc(sizeof(struct ipheader));
        struct tcpheader *tcph = (struct tcpheader *) malloc( sizeof (struct tcpheader));
        struct body *bo = (struct body *) malloc( sizeof (struct body));
        struct ps_hdr *ps = (struct ps_hdr *) malloc( sizeof (struct ps_hdr));
    
        datagram = (char *) malloc(sizeof(struct ipheader) + sizeof(struct tcpheader)+sizeof (struct body));
    
        struct sockaddr_in sin;
    
        iph= (struct ipheader *) datagram;
        tcph=   (struct tcpheader *) (datagram+ sizeof(struct ipheader));
        bo= (struct body *) (datagram+sizeof(struct ipheader)+ sizeof(struct tcpheader));
      memset(bo->data,'\0',strlen((char *)bo->data));
    
      sin.sin_family = AF_INET;
      sin.sin_port = htons (PORT);
      sin.sin_addr.s_addr = inet_addr ("193.99.144.71");
    
    printf("%i\n",sizeof(datagram));
      iph->ip_hl = 5;
      iph->ip_v = 4;
      iph->ip_tos = 0;
      iph->ip_len = sizeof (struct ipheader) + sizeof (struct tcpheader)+sizeof(struct body);
    
      iph->ip_id = 1;
      iph->ip_off = 0;
      iph->ip_ttl = 255;
      iph->ip_p = 6;
      iph->ip_sum = 0;
      iph->ip_src = inet_addr ("192.168.0.113");
      iph->ip_dst = sin.sin_addr.s_addr;
    
      tcph->th_sport = htons (1234);
      tcph->th_dport = htons (PORT);
      tcph->th_seq = rand();
      tcph->th_ack = htons (6234);
      tcph->th_x2 = 0;
      tcph->th_off = 5;
      tcph->th_flags = 16; // SYN
      tcph->th_win = htons(65535);
      tcph->th_sum = 0;
      tcph->th_urp = 0;
    
      // Build the Psuedo Header
    
      ps->source_address   = inet_addr ("192.168.0.113");
      ps->dest_address  = sin.sin_addr.s_addr;
      ps->placeholder  = 0;
      ps->protocol  = IPPROTO_TCP;
      ps->tcp_length  = htons(sizeof(struct tcpheader)+sizeof(struct body));
    
        ps->tcp = *tcph;
      ps->data=*bo;
    
    strcpy((char *)bo->data,info);
    // Calculate Checksum
    
      tcph->th_sum = checksum((unsigned short *)ps, sizeof(struct ps_hdr));
      iph->ip_sum  = checksum((unsigned short *)iph, sizeof(struct ipheader));
    
      // ENABLE IPHDRINCL
    
        if (setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&bOpt, sizeof(bOpt)) == SOCKET_ERROR)
        {
       printf("setsockopt(IP_HDRINCL) failed: %d\n", WSAGetLastError());
       return -1;
        }
    
          // Send The Packet
    
        if (sendto(s, datagram, iph->ip_len, 0, (SOCKADDR *)&sin, sizeof(sin)) == SOCKET_ERROR)
        {
              printf("sendto() failed: %d\n", WSAGetLastError());
       return -1;
        }
    
      return 0;
    }
    

    ------------------------------------------EOF--------------------------------

    --------------------------------------check.cpp----------------------------

    #include "head.h"
    
    unsigned short checksum(unsigned short *addr, int len)
    {
        register int sum = 0;
        u_short answer = 0;
        register u_short *w = addr;
        register int nleft = len;
    
        /*
         * 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)
          {
      *(u_char *) (&answer) = *(u_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 = ~sum;/* truncate to 16 bits */
        return (answer);
    }
    

    ----------------------------------EOF-------------------------------------


Anmelden zum Antworten