Find the answer to your Linux question:
Results 1 to 3 of 3
I'm using the following function to create a tcp SYN packet and send it. Im expecting an RST from the destination : the tcp packet has 20bytes tcpheader, 44 bytes ...
Enjoy an ad free experience by logging in. Not a member yet? Register.
  1. #1
    Just Joined!
    Join Date
    Feb 2006
    Posts
    11

    Help needed: constructing TCP SYN packet


    I'm using the following function to create a tcp SYN packet and send it. Im expecting an RST from the destination :
    the tcp packet has 20bytes tcpheader, 44 bytes data. (total 64 bytes )

    main()
    {
    .....
    s = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
    .....
    ....
    send_packet();
    recvfrom(s, ...);
    ...
    }

    void send_packet()
    {
    u_char outpack[PING_MAXPACKET];
    bzero(outpack,PING_MAXPACKET);
    struct tcphdr *tcph = (struct tcphdr*)outpack;
    tcph->source = htons(MYPORT);
    tcph->dest = htons(THEIRPORT);
    tcph->seq = htonl(seqno);
    tcph->ack_seq = 0;

    *((u_int8_t*)(outpack+12)) = 80; //to set the data offset to 5 (20 bytes)
    *((u_int8_t*)(outpack+13)) = 2; // to set SYN flag
    //tcph->window = 1000;
    tcph->check = in_cksum(tcph,64);

    int i = sendto( s, outpack, 64, 0, &whereto, sizeof(struct sockaddr) );
    // struct sockaddr whereto is filled with destination IP,port
    }

    I did not receive TCP RST from dest IP. Ethereal shows an error in the checksum. I used the checksum function used in ping program:

    in_cksum(u_short *addr, int len)
    {
    u_short *w = addr;
    int sum = 0;
    for (sum = 0; len > 0; len--)
    sum += *w++;
    sum = (sum >> 16) + (sum & 0xffff);
    sum += (sum >> 16);
    return ~sum;
    }

    Please correct me where I went wrong. Include code if possible. Iam running it on Fedora Core 3 (kernel 2.4.20-8 )
    Thanx

  2. #2
    Just Joined!
    Join Date
    Apr 2006
    Posts
    5
    I think when u r sending ur syn packet better use struct sockaddr_ll structure in the destination field( as u are using raw socket ).also use the size of that structure.

    struct sockaddr_ll toaddr;

    sendto(sock,packet_to_send,sizeof(packet),0,(strcu t sockaddr*)&toaddr,sizeof(struct sockaddr_ll));

    i think this should work.

    if it works then plz tell me.

  3. #3
    Just Joined!
    Join Date
    Feb 2006
    Posts
    11
    Thanx for the reply, hex.
    Actually I came to know where I went wrong (see the tcp_cksum function comments):

    #define DATASIZE 12

    /* this function calculates the TCP-checksum with its pseudo-header */
    u_short tcp_cksum(struct iphdr *ip, struct tcphdr *tcp)
    {
    char header[100], *p = header; // header size shud be enuf to acomdate pseudo+actual hdrs,data

    /* the pseudo-header includes the source-address, the destination-
    * * address (each 32 bit), 8 bit set to zero, 8 bit with the protocol
    * * and 16 bit with the TCP-packet's length. The rest of the header
    * * is the 'real' TCP-header.
    * */
    *(unsigned long*)p = ip->saddr;
    p += 4;
    *(unsigned long*)p = ip->daddr;
    p += 4;
    *p = 0;
    p++;
    *p = ip->protocol;
    p++;
    //*(unsigned short*)p = htons(4 * tcp->doff); THIS IS WHERE I WENT WRONG. I forgot to include the data size
    *(unsigned short*)p = htons(4 * tcp->doff +DATASIZE); // 20 tcphdr bytes + 12 data bytes
    p += 2;
    //memcpy(p, tcp, 4 * tcp->doff);
    memcpy(p, tcp, 4 * tcp->doff +DATASIZE);

    //return in_cksum((unsigned short*)header, 32);
    return in_cksum((unsigned short*)header, 32+DATASIZE); // 12 pseudo hdr + 20 tcphdr + 12 data bytes
    }


    I also included code to create the SYN packet, in case som1 else needs it



    /* this function sends the SYN-packets out to the net */
    int do_scan(int s, unsigned long src, unsigned long dst,
    unsigned short lo, unsigned short hi)
    {
    struct iphdr *ip;
    struct tcphdr *tcp;
    char packet[sizeof(*ip) + sizeof(*tcp)+ DATASIZE]; // header + 12 data bytes
    struct sockaddr_in to;
    unsigned short i;

    ip = (struct iphdr*) packet;
    tcp = (struct tcphdr*) (packet + sizeof(*ip));

    memset(packet, 0, sizeof(packet));

    ip->ihl = 5;
    ip->version = 4;
    ip->tot_len = htons(sizeof(packet));
    ip->ttl = 64;
    ip->protocol = IPPROTO_TCP;
    ip->saddr = src;
    ip->daddr = dst;
    ip->check = in_cksum((unsigned short*)ip, sizeof(*ip));

    to.sin_addr.s_addr = dst;
    to.sin_family = AF_INET;
    to.sin_port = 0; /* filled later */

    tcp->doff = 5;
    tcp->source = htons(1024);
    tcp->seq = rand();
    tcp->syn = 1;
    tcp->window = htons(1024);

    for(i = lo; i <= hi; i++)
    {
    usleep(USLEEP_MS);
    tcp->dest = htons(i);
    tcp->check = 0;

    tcp->check = tcp_cksum(ip, tcp);
    //tcp->check = 0;

    if (sendto(s, packet, sizeof(packet), 0,
    (struct sockaddr*)&to, sizeof(to)) == -1)
    {
    perror("sendto() failed");
    return 1;
    }
    }
    close(s);
    return 0;
    }

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •