简体   繁体   中英

Checking return address in recvfrom() (C UDP Sockets)

This pertains to attempting to validate the return address in recvfrom() (the fifth argument to the function) in this UDP echo client:

While I can send data to the server and receive return communications correctly, I'm having trouble validating the return IP address when comparing the fromAddr.sin_addr and echoServAddr.sin_addr.

The goal here is to compare the address in the structure that was used in sendto() and the address in the structure returned from recvfrom() to validate the echo reply from the server indeed came from where the initial transmission from the client was sent (A rudimentary POC that there wasn't a Man In The Middle).

What should I be looking at in order to appropriately validate the return address as it is returned from recvfrom() matches the address transmitted to as referenced in the sendto() call?

#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);

}

If the source IP/port of the incoming packet is the same as the destation IP/port of the packet you sent, then the sin_addr and sin_port fields of echoServAddr and fromAddr should match.

This line of code however doesn't do that:

if ((struct sockaddr *) &echoServAddr.sin_addr != (struct sockaddr *) &fromAddr.sin_addr) {

This is comparing the address of echoServAddr.sin_addr against the address of fromAddr.sin_addr . Because these are two separate variables, this will always be false. You instead want:

if ((echoServAddr.sin_addr.s_addr != fromAddr.sin_addr.s_addr) || 
    (echoServAddr.sin_port != fromAddr.sin_port))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM