C - 使用原始套接字创建TCP SYN而不填充IP头

时间:2016-03-29 18:13:35

标签: c linux raw-sockets

我希望我的应用程序创建TCP SYN数据包并在网络上发送。我没有使用IP_HDRINCL设置setsockopt,因为我希望内核填充IP标头。

我试过

  1. 使用字节缓冲区包含TCP标头+有效负载
  2. 使用字节缓冲区包含IP标头+ TCP标头+有效负载。
  3. 以上两种方法都返回sendto错误-1,错误号设置为88 以下是我使用的代码

    #include <sys/socket.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <netinet/ip.h>
    #include <netinet/tcp.h>
    #include <errno.h>
    
    int main()
    {
        int sockfd;
    
        if(sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP) < 0)
        {
            printf("sokcet functin failed : \n");
            exit (-1);
        }
    
        char packet[512];
    
        struct sockaddr_in remote; // remote address
    
        struct iphdr *ip = (struct iphdr *) packet;
        struct tcphdr *tcp = (struct tcphdr *) packet + sizeof(struct iphdr);
    
    
        /*
        struct tcphdr *tcp = (struct tcphdr *) packet; // tcp header
        */
        remote.sin_family = AF_INET; // family
        remote.sin_addr.s_addr = inet_addr("192.168.0.57"); // destination ip
        remote.sin_port = htons(atoi("3868")); // destination port
    
        memset(packet, 0, 512); // set packet to 0
    
        tcp->source = htons(atoi("6668")); // source port
        tcp->dest = htons(atoi("3868")); // destination port
        tcp->seq = htons(random()); // inital sequence number
        tcp->ack_seq = htons(0); // acknowledgement number
        tcp->ack = 0; // acknowledgement flag
        tcp->syn = 1; // synchronize flag
        tcp->rst = 0; // reset flag
        tcp->psh = 0; // push flag
        tcp->fin = 0; // finish flag
        tcp->urg = 0; // urgent flag
        tcp->check = 0; // tcp checksum
        tcp->doff = 5; // data offset
    
        int err;
        if((err = sendto(sockfd, packet, sizeof(struct iphdr), 0, (struct sockaddr *)&remote, sizeof(struct sockaddr))) < 0)
        { // send packet
            printf("Error: Can't send packet : %d %d !\n\n", err, errno);
            return -1;
        }
    

    为什么我得到sendto错误-1和错误88?

    另外,我想知道如何确定sendto函数中第二个参数中使用的数据长度。如果我硬编码为包字节缓冲区的大小,即512字节,是不是错了?

2 个答案:

答案 0 :(得分:0)

这里我没有给出解决方案,但是 你可以检查你的错误的含义,并可以纠正你的错误,我也不能评论,因为我没有太多的声誉..我只是想帮助...

int err = sendto(sockfd, packet, sizeof(struct iphdr), 0, (struct sockaddr *)&remote, sizeof(struct sockaddr)));
int saved_error = errno;  // Save errno flag that is set by sendto.
if(err < 0) {
    fprintf(stderr, "Send Error: %s\n", strerror(saved_error));
}

我认为这可能有所帮助......但这不是答案......这将给出错误的含义,以便您可以纠正错误..

答案 1 :(得分:0)

对于SOCK_RAW,您可以使用AF_ATMPVC:访问原始的ATM PVC

在您的代码中:

if((sockfd = socket(AF_ATMPVC, SOCK_RAW, IPPROTO_TCP)) < 0)

我希望这会有所帮助