Ошибка с функцией sendto (): ошибка недопустимого аргумента - PullRequest
1 голос
/ 28 мая 2020

Я работаю над написанием программы ping CLI для linux и получаю ошибку 22: недопустимый аргумент в функции sendto (). Я не понимаю, почему, все аргументы кажутся правильными.

Вот где я вызываю функцию:

    // send echo request
    bytesSent = sendto(socketFD,                                                        // socket file descriptor
                      (char*)&packet, PacketSize,                                       // packet and size
                      0,                                                                // flags
                      (sockaddr*)DestinationAddr, (socklen_t)sizeof(DestinationAddr));  // destination address and size

'пакет' выглядит так: (Я вызываю initializePacket ( ) в функции, в которой я вызываю sendto ())

struct PacketData {
    icmphdr header;
    char message[PacketSize - sizeof(header)];      // want total size to be 64 bytes
};

PacketData initializePacket(int &transmitted) {
    PacketData packet = {};

    packet.header.type = ICMP_ECHO;                 // set ICMP type to Echo
    packet.header.un.echo.id = getpid() & 0xFFFF;   // set id (ICMP field is 16 bits)
    packet.header.checksum = 0;                     // fixed checksum because data is unchanging
    packet.header.un.echo.sequence = transmitted++;

    // fill up message
    memset(&packet.message, '0', sizeof(packet.message));
    packet.message[PacketSize - sizeof(packet.header) - 1] = '\0';

    return packet;
}

'DestinationAddr' это:

    // variables needed to store IP Address
    addrinfo* result;
    sockaddr_in* DestinationAddr;
    char ipString[INET_ADDRSTRLEN];

    // get IP Address and store in result (passed by reference)
    if (getIPAddress(argv[1], result) != 0) {
        std::cout << "Invalid IP Address. Terminating ...\n";
        exit(EXIT_FAILURE);
    }
    else {
        DestinationAddr = (sockaddr_in*)result->ai_addr;                        // get struct from resulting linked list
        void* address;
        address = &DestinationAddr->sin_addr;                                   // store IP Address
        inet_ntop(result->ai_family, address, ipString, sizeof(ipString));      // convert binary IP to string
        std::cout << "IP: " << ipString << std::endl;
    }

И функция getIPAddress ():

int getIPAddress(char* hostName, addrinfo* &result) {
    addrinfo tempStruct = {0};

    tempStruct.ai_family = AF_INET;         // want IPv4
    tempStruct.ai_socktype = SOCK_DGRAM;    // set socket type to datagram
    tempStruct.ai_flags = AI_PASSIVE;       // fill in IP automatically

    // get and validate IP address
    return (getaddrinfo(hostName, &PortNo, &tempStruct, &result));
}

Номер порта определяется как: const char PortNo = '0';

1 Ответ

0 голосов
/ 29 мая 2020

Согласно документации icmp :

Пользовательский протокол может получать пакеты ICMP для всех локальных сокетов, открывая необработанный сокет с протоколом IPPROTO_ICMP.

Итак, попробуйте создать свой сокет следующим образом:

socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)

И, если вы столкнетесь с ошибкой EPERM, запустите вашу программу как root.

...