【问题标题】:C Networking: Sendto() returning Errno 22, EINVALC 网络:Sendto() 返回 Errno 22、EINVAL
【发布时间】:2019-05-26 23:42:46
【问题描述】:

我正在尝试使用第 2、3 和 4 层组件(即以太网、IP 和 UDP)从头开始生成数据包。我的套接字配置为使用 SOCK_RAW 作为类型,使用 IPPROTO_RAW 作为协议,以便以后可以使用我的程序发送不同的协议。我严格遵守 sendto(2) 手册页 (https://linux.die.net/man/2/sendto),但是,我似乎仍然无法通过本地主机传输数据包。我的程序返回的错误是 22,即 EINVAL,表示我传递了一个错误的参数。

我已经使用Sockets sendto() returning EINVALSocket programming: sendto always fails with errno 22 (EINVAL) 来尝试解决我的问题。我什至将套接字切换为使用 SOCK_DGRAM 作为类型并使用 IPPROTO_UDP 作为协议,以查看它是否与套接字有关(尽管我不相信这会提示错误的参数响应)。

我的代码如下:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/ip.h>
#include <netinet/ether.h>
#include <netinet/udp.h>
#include <sys/socket.h>
#include <errno.h>

#define BUFFER 1024

int main(int argc, char *argv[]) {

        /* Socket Creation */
    int sockfd;

    if ((sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) == -1) {
            perror("Socket");
            exit(EXIT_FAILURE);
    }

    // This will hold all of the packet's contents
    char sendbuf[BUFFER];


    /* Address Stuff */

    // Specify Address
    in_addr_t address = inet_addr("127.0.0.1");

    // Specifying Address for Sendto()
    struct sockaddr_in sendto_addr;
    memset(&sendto_addr, 0, sizeof(sendto_addr));
    sendto_addr.sin_family = AF_INET;
    sendto_addr.sin_port = htons(9623);  // Make sure the port isn't contested
    sendto_addr.sin_addr.s_addr = address;

    // Size of whole packet
    size_t total_len = 0;


    /* LAYER 2 */
    // Ethernet Header Configuration
    struct ether_header *ether = (struct ether_header *)sendbuf;
    int i;
    for (i = 0; i < 6; ++i) {
        ether -> ether_dhost[i] = 0x00; // Temporary data fill
        ether -> ether_shost[i] = 0x00; // Temporary data fill
    }
    ether -> ether_type = ETHERTYPE_IP;

    total_len += sizeof(struct ether_header);


    /* LAYER 3 */
    // IP Header Configuration
    struct ip *ip = (struct ip *)(sendbuf + sizeof(struct ether_header));

    ip -> ip_hl = 5;
    ip -> ip_v = 4;
    ip -> ip_tos = 0;
    ip -> ip_p = 17;
    ip -> ip_ttl = 255;
    ip -> ip_src.s_addr = address;
    ip -> ip_dst.s_addr = address;  

    total_len += sizeof(struct ip); 


    /* LAYER 4 */
    // UDP Header Configuration
    struct udphdr *udp = (struct udphdr *)(sendbuf + sizeof(struct ether_header) + \
                                           sizeof(struct ip));

    udp -> source = 123; // Gibberish to fill in later
    udp -> dest = 321;   // Gibberish to fill in later
    udp -> check = 0;

    total_len += sizeof(struct udphdr);


    /* Giberrish Packet Data */
    sendbuf[total_len++] = 0x00;
    sendbuf[total_len++] = 0x00;
    sendbuf[total_len++] = 0x00;
    sendbuf[total_len++] = 0x00;


    /* Fill in Rest of Headers */
    udp -> len = htons(total_len - sizeof(struct ether_header) - sizeof(struct ip));
    ip -> ip_len = htons(total_len - sizeof(struct ether_header));


    /* Send Packet */  // ERROR OCCURS HERE
    printf("Sockfd is %d\n", sockfd);
    printf("Total length is %d\n", total_len);
    if (sendto(sockfd, sendbuf, total_len, 0, (const struct sockaddr*)&sendto_addr, \
        sizeof(sendto_addr)) < 0) {
            printf("Error sending packet: Error %d.\n", errno);
            perror("sendto Error");
            exit(EXIT_FAILURE);
    } 

    close(sockfd);

}

确切的控制台消息状态:

Sockfd 为 3
总长度为 46
发送数据包时出错:错误 22。
sendto 错误:参数无效

【问题讨论】:

  • 您正在运行什么操作系统/内核?还有#define BUFFER 65535char sendbuf[BUFFER]; - 那是65 KiB 的内存,很多。通常操作系统不允许在堆栈上分配超过 4Kb 的空间。
  • @KamilCuk 操作系统:Red Hat Enterprise Linux v. 7.6 // 内核:3.10.0-957.12.1.el7.x86_64 // 我已将其降低到 1024,谢谢您的建议!

标签: c sockets networking arguments sendto


【解决方案1】:

尤里卡!原来是这一行:

if ((sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) == -1) {
        perror("Socket");
        exit(EXIT_FAILURE);
}

应该是这样的

if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
        perror("Socket");
        exit(EXIT_FAILURE);
}

为什么这解决了问题?很好的问题,很想看到有人对此主题的回应:P

【讨论】:

    猜你喜欢
    • 2011-04-29
    • 2014-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-19
    • 1970-01-01
    • 1970-01-01
    • 2013-03-25
    相关资源
    最近更新 更多