How can I know the sendto function which argument is invalid and why it is invalid?

Viewed 40

TCP connections require three handshakes, I want to send TCP packets with SYN = 1 manually, that is, the first handshake.Here is my code:

#include <iostream>
#include <thread>
#include <map>
#include <vector>
#include "PackageData.hpp"
#include "utils.hpp"
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>      // for socket
#include <netinet/tcp.h>    // for tcp
#include <netinet/ip.h>     // for ip

unsigned char* GetData(sockaddr_in addr)
{
    unsigned int len = sizeof(struct ip)+sizeof(struct tcphdr);
    unsigned char * buffer  = new unsigned char [len];
    memset(buffer,0,sizeof(buffer));
    struct ip *ip_ptr;
    struct tcphdr *tcp_ptr;

    ip_ptr = (struct ip *)buffer;
    tcp_ptr = (struct tcphdr *)(buffer+sizeof(struct ip));

    ip_ptr->ip_v = IPVERSION;
    ip_ptr->ip_hl = sizeof(struct ip)>>2;
    ip_ptr->ip_tos = 0;
    ip_ptr->ip_len = htons(len);
    ip_ptr->ip_id = 0;
    ip_ptr->ip_off = 0;
    ip_ptr->ip_ttl = MAXTTL;
    ip_ptr->ip_p = IPPROTO_TCP;
    ip_ptr->ip_sum = 0;
    ip_ptr->ip_dst = addr.sin_addr;


    
    tcp_ptr->dest = addr.sin_port;
    tcp_ptr->seq = 0;
    tcp_ptr->ack_seq = 0;
    tcp_ptr->doff = 5;  
    //res2+urg+ack+psh+rst+syn+fin 8
    //tcp->res2 = 0;
    //tcp->urg = 0;
    //tcp->ack = 0;
    //tcp->psh = 0;
    //tcp->rst = 0;
    tcp_ptr->syn = 1;
    //tcp->fin = 0;
    //tcp->window = 0;


    //random source ip and port to cheat
    uint32_t m_ip = random();
    ip_ptr->ip_src.s_addr = htonl(m_ip);
    tcp_ptr->source = htons(random());
     

    //will be calculated by kernel,just a fake head here 
    ip_ptr->ip_sum = htons(sizeof(struct tcphdr));

    tcp_ptr->check = CheckSum((uint16_t *)buffer+4,sizeof(buffer)-8);

    return buffer;


}
void SendOne(uint32_t ip,int port)
{
        cout<<"send to " <<ip_to_string(ip)<<endl;

        sockaddr_in dst_ip = { 0 };
        dst_ip.sin_family = AF_INET;
        dst_ip.sin_addr.s_addr = inet_addr(ip_to_string(ip).data());
        dst_ip.sin_port = htons(port);
  
        int sock = socket(AF_INET,SOCK_RAW,IPPROTO_RAW);
        int on = 1;
        int opt =  setsockopt(sock,IPPROTO_IP,IP_HDRINCL,&on,sizeof(on));
        cout<<"sock:"<<sock<<" errno:"<<errno<<" desc:"<<strerror(errno)<<endl;
  

        unsigned char * buffer = GetData(dst_ip);
        unsigned int len = sizeof(struct ip)+sizeof(struct tcphdr);
        int re = sendto(sock, //re is here
        buffer,
        len,
        0,
        (sockaddr*)&dst_ip,
        sizeof(dst_ip));
        cout<<"re:"<<re<<" errno:"<<errno<<" "<<strerror(errno)<<endl;
}

The SendOne is a function that send a SYN=1 package to ip:port.The GetData is a function to generate the buffer to send. However, when I run my code in linux(wsl version 1,ubuntu 20.04),it's re is -1,and the errno was set to 22, which means invalid arguments.

enter image description here

I just want to know:

  1. Why did such a mistake occur? If it is hard, I just want to know the other question 2.
  2. Is there a way to get more detailed error information, such as which parameter is invalid and why?
1 Answers

I upload my code to the cloud server (CentOS 8), and it will work correctly. I don't know why. I guess WSL has made some changes, which makes me waste a day.

Related