在recvfrom()中检查返回地址(C UDP套接字)

时间:2018-10-19 19:46:54

标签: c

这与尝试在此UDP回显客户端中的recvfrom()(函数的第五个参数)中验证返回地址有关:

虽然我可以将数据发送到服务器并正确接收返回通信,但是在比较fromAddr.sin_addr和echoServAddr.sin_addr时,我无法验证返回IP地址。

这里的目标是比较sendto()中使用的结构中的地址与recvfrom()返回的结构中的地址,以验证来自服务器的回显应答确实来自客户端的初始传输。已发送(基本POC,说中间没有人)。

我应该看什么才能正确验证从recvfrom()返回的返回地址是否与sendto()调用中引用的发送地址相匹配?

#include <stdio.h>      /* for printf() and fprintf() */
#include <sys/socket.h> /* for socket(), connect(), sendto(), and recvfrom() */
#include <arpa/inet.h>  /* for sockaddr_in and inet_addr() */
#include <stdlib.h>     /* for atoi() and exit() */
#include <string.h>     /* for memset() */
#include <unistd.h>     /* for close() */

#define ECHOMAX 255     /* Longest string to echo */

void DieWithError(char *errorMessage);  /* External error handling function */

int main(int argc, char *argv[])
{
    int sock;                        /* Socket descriptor */
    struct sockaddr_in echoServAddr; /* Echo server address */
    struct sockaddr_in fromAddr;     /* Source address of echo */
    unsigned short echoServPort;     /* Echo server port */
    unsigned int fromSize;           /* In-out of address size for recvfrom() */
    char *servIP;                    /* IP address of server */
    char *echoString;                /* String to send to echo server */
    char echoBuffer[ECHOMAX+1];      /* Buffer for receiving echoed string */
    int echoStringLen;               /* Length of string to echo */
    int respStringLen;               /* Length of received response */

    // manage the command line arguments and errors
    if ((argc < 3) || (argc > 4)) {
        fprintf(stderr, "Usage: %s <Server IP> <Echo Word> [<Echo Port>]\n",
            argv[0]);
        exit(1);
        }
    // load servIP
    servIP = argv[1];
    // load echoString
    echoString = argv[2];
    // check echoString and error if too long
    echoStringLen = strlen(echoString);
    if (!(echoStringLen <= 255)) {
        DieWithError("BUFFER EXCEEDED ERROR");
    }
    // load port
    if (argc == 4)
        echoServPort = atoi(argv[3]);
    else
        echoServPort = 7;
    // create the socket
    if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
        DieWithError("SOCKET CREATION ERROR");
    }
        /* Construct the server address structure */
        memset(&echoServAddr, 0, sizeof(echoServAddr));    /* Zero out structure */
        echoServAddr.sin_family = AF_INET;                 /* Internet addr family */
        echoServAddr.sin_addr.s_addr = inet_addr(servIP);  /* Server IP address */
        echoServAddr.sin_port   = htons(echoServPort);     /* Server port */

    // send the string
    inet_pton(AF_INET, servIP, &echoServAddr.sin_addr);
    if ((sendto(sock, echoString, strlen(echoString), 0, (struct sockaddr *)
        &echoServAddr, sizeof(echoServAddr))) < 0) {
        DieWithError("SEND ERROR");
    }
    // recieve a response
    respStringLen = recvfrom(sock, echoBuffer, sizeof(echoBuffer), 0,
        (struct sockaddr *) &fromAddr, &fromSize);
    if (respStringLen < 0) {
        DieWithError("RECV ERROR");
    }
    // print the message sent
    printf("SENT FROM CLIENT: '%s'\n", echoString);
    // print the message recieved
    echoBuffer[respStringLen] = '\0';
    printf("RECEIVED FROM SERVER: '%s'\n", echoBuffer);
    // check if from the correct server
    if ((struct sockaddr *) &echoServAddr.sin_addr != (struct sockaddr *) &fromAddr.sin_addr) {
        DieWithError("INVALID RETURN ADDRESS");
    }
    // close the socket
    close(sock);
    // exit the program
    exit(0);

}

1 个答案:

答案 0 :(得分:3)

如果传入数据包的源IP /端口与您发送的数据包的降级IP /端口相同,则sin_addr和{的sin_portechoServAddr字段{1}}应该匹配。

但是这行代码不能做到这一点:

fromAddr

这是将if ((struct sockaddr *) &echoServAddr.sin_addr != (struct sockaddr *) &fromAddr.sin_addr) { 地址echoServAddr.sin_addr地址进行比较。由于这是两个单独的变量,因此始终为false。相反,您想要:

fromAddr.sin_addr