LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 09-29-2010, 01:51 AM   #1
Lantzvillian
Member
 
Registered: Oct 2007
Location: BC, Canada
Distribution: Fedora, Debian
Posts: 210

Rep: Reputation: 41
Question Get source IP from UDP socket using recv()


Hi all,

I am in a bit of a pickle. I have scoured google for ways to get the source address of the client sent to my server which receives using UDP sockets.

I get the packet with no issue, but I would like to get the source address. Where it currently uses 192.168.0.103, I would like it to be this address.

Any Ideas?

Code:
#include "rbsocket.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

/// Address and port info to send/recv to/from
#define SERVER_PORT 7001
#define SERVER_DPORT 7000
#define CLIENT_PORT 12345

/// Buffer size for reading - smaller size = more packets sent
#define BUFFER_SIZE 1024

// forward declaration since C is a parse once compiler
long fileSize(char *filename);

int main() {
    struct sockaddr_in srcaddr; // client address - ( not really needed for this example )
    struct sockaddr_in srcaddr2;
    int srcaddrSize; // client address size - ( not really needed for this example )
    FILE *output; // file to output to
    long outputSize = 0; // to store the expected # bytes to receive from client
    char buffer[BUFFER_SIZE]; // buffer to use for recving & writing
    int bread = 0; // temp-var for bytes read from socket
    int bwritten = 0; // temp-var for bytes written to file
    int fd, fd2; // socket descriptor
    
    printBanner();


    fd = get_bound_udp_socket(SERVER_ADDR, SERVER_PORT); //  Open socket for controls
    fd2 = get_bound_udp_socket(SERVER_ADDR, SERVER_DPORT);
    while (1) {

        struct cmd_s *cmdrecieved;
        char bufferd[BUFFER_SIZE];

        recvfrom(fd, bufferd, BUFFER_SIZE, 0, (struct sockaddr *) & srcaddr, (socklen_t*) & srcaddrSize);

        cmdrecieved = (struct cmd_s *) bufferd;
        printf("Server recieved-> cmd: %s \n", cmdrecieved->cmd); // This works

        //This is what I would like it to do
        if (strncmp(cmdrecieved->cmd, "send", 3) == 0) {
            //  Prepare command packet to be sent to the client.
            prep_sockaddr_in(&srcaddr2, "0.0.0.0", CLIENT_PORT);


            //  This is the control packet to tell the client to start sending to port 7000
            struct cmd_s cmdsent;
            memset(&cmdsent, 0, sizeof (cmdsent));
            strcpy(cmdsent.cmd, "rvck"); // rvck means I am ready to recieve fire away old boy.
            strcpy(cmdsent.filename, "0xBEEF");
            printf("Server sent-> cmd: %s\n", cmdsent.cmd); //this works
            sendto(fd2, (char *) & cmdsent, sizeof (cmdsent), 0, (struct sockaddr *) & srcaddr, sizeof (srcaddr));

            // 	// open file to save to
            output = fopen(cmdrecieved->filename, "w");
            // if either open failed 
            if ((fd2 == -1) || (output == NULL)) { // print error
                printf(" ERROR: %s \n", strerror(errno));
                // cleanup any open file/socket
                if (output)
                    fclose(output);
                if (fd2 != -1)
                    close(fd2);
                // bail
                return -1;
            }
            // recieve from the client the file size 
            //   so we know how many bytes to expect

            bread = recvfrom(fd2, &outputSize, sizeof (outputSize), 0,
                    (struct sockaddr *) & srcaddr2,
                    (socklen_t*) & srcaddrSize);

            // check that we received a filesize 
            if (bread != sizeof (outputSize)) { // if not print error
                printf(" ERROR: failed to read file size: %d:%s\n",
                        errno, strerror(errno));
                // cleanup
                close(fd2);
                fclose(output);
                // bail 
                return -1;
            }
            // Now we can loop until either 
            //  we error in reading from the ssocket 
            //  - or we received all the expected bytes 
            while (bread > 0 && outputSize > 0) // while we have read stuff  
            {
                // read some file data from the socket 
                //   in this example - we do not care about whom the data is from
                bread = recvfrom(fd2, buffer, BUFFER_SIZE, 0,
                        (struct sockaddr *) & srcaddr,
                        (socklen_t*) & srcaddrSize);
                // did we read something ?
                if (bread > 0) { // read stuff - write it to file
                    bwritten = fwrite(buffer, 1,
                            bread, output);
                    // check that we wrote the received data to the file
                    if (bwritten != bread) // wtf!
                    {
                        // print error
                        printf(" write to file fail! :%d: %s\n", errno, strerror(errno));
                        // get out of loop to cleanup
                        break;
                    }
                    // lower the remaining expected bytes
                    outputSize -= bwritten;
                    printf(" Recv: %d bytes -\t %ld bytes remaining \n", bwritten, outputSize);
                } else { // We had some error reading the socket 
                    printf(" Socket read failed \n");
                    // get out of loop to cleanup
                    break;
                }

            }
            if (output) {
                fclose(output);
            }
        }
        if (strncmp(cmdrecieved->cmd, "get", 3) == 0) {
            long inputSize = 0; // to store the file size

            //  Prepare command packet to be sent to the client.
            prep_sockaddr_in(&srcaddr2, "0.0.0.0", CLIENT_PORT);

            //  Open file to write
            FILE *input = fopen(cmdrecieved->filename, "r");

            //  If file exists - start transfer
            //  If file does not exist - send error message to client
            if (input) {
                printf("File exists -> commencing sending to client\n");

                struct cmd_s cmdsent;
                memset(&cmdsent, 0, sizeof (cmdsent));
                strcpy(cmdsent.cmd, "sdck");
                strcpy(cmdsent.filename, "0xBEEF\n");
                printf("Server sent-> cmd: %s\n", cmdsent.cmd);
                sendto(fd2, (char *) & cmdsent, sizeof (cmdsent), 0, (struct sockaddr *) & srcaddr, sizeof (srcaddr));

                if ((fd2 == -1) || (input == NULL)) { // puke error
                    printf(" ERROR: %s \n", strerror(errno));
                    // cleanup open socket or file 
                    if (fd2 != -1) close(fd2);
                    if (input != NULL) fclose(input);
                    // bail 
                    return -1;
                }
                // We need to send the filesize so the server knows
                //   how much data to expect
                // get the size
                if ((inputSize = fileSize(cmdrecieved->filename)) == -1) {
                    printf(" Server didn't recieve size packet \n");
                    // cleanup open files / sockets
                    close(fd);
                    fclose(input);
                    // bail
                    return -1;
                }

                //Send the size to the client - ( single packet containing a long = fileSize in bytes)
                bwritten = sendto(fd2, &inputSize, sizeof (inputSize), 0,
                        (struct sockaddr *) & srcaddr2, sizeof (srcaddr2));

                // verify that it was all sent - ( or so the stack thinks )
                if (bwritten != sizeof (inputSize)) {
                    printf(" send of filesize failed: %d: %s \n", errno, strerror(errno));
                    // cleanup open files / sockets
                    close(fd2);
                    fclose(input);
                    // bail
                    return -1;
                }
                // yippy - now we can beam inputSize bytes to the server
                // While there is stuff to send - and we have not sent inputSize bytes
                while (!feof(input) && inputSize > 0) { // read some data from file
                    bread = fread(buffer, 1, BUFFER_SIZE, input);
                    if (bread > 0) { // if there was no read error
                        // send the data read to the server
                        bwritten = sendto(fd2, buffer, bread, 0, (struct sockaddr *) & srcaddr2,
                                sizeof (srcaddr2));

                        // check if we sent it all - ( or at least the stack thinks so )
                        if (bwritten != bread) // wtf
                        { // doh!
                            printf(" Socket Write failed: %d: %s\n",
                                    errno, strerror(errno));
                            // get out of loop - in order to cleanup
                            break;
                        }
                        // decriment the size remaining
                        inputSize -= bwritten;
                        printf(" Sent: %d bytes -\t %ld bytes remaining \n", bwritten, inputSize);
                    } else if (bread < 0) { // We had some error reading the file 
                        printf(" file read error %d: %s\n", errno, strerror(errno));
                        // get out of loop - in order to cleanup
                        break;
                    }
                    // End case - (bread = 0) - only occurs if there is nothing remaining 
                    // in the file to read.
                } //End for while loop

                fclose(input);
            }
            else {
                //  This is the control packet to tell the client there was an error 
                //  - uses port 7000
                struct cmd_s cmdsent;
                memset(&cmdsent, 0, sizeof (cmdsent));
                strcpy(cmdsent.cmd, "err");
                strcpy(cmdsent.filename, "ERROR: File not found!\n");
                printf("Server sent-> cmd: %s\n", cmdsent.cmd);
                sendto(fd2, (char *) & cmdsent, sizeof (cmdsent), 0, (struct sockaddr *) & srcaddr, sizeof (srcaddr));
                close(fd2);
            }

        }
    }

    // cleanup 
    close(fd);
    return 0;
}

//  Function to display server banner
void printBanner() {
  printf("\n========================\n");
  printf("\n     File Muncher       \n");
  printf("\n========================\n");
  printf("Version: 1.0\n");
  printf("\nServer Listening on UDP 7001 \n");
}

/// returns the filesize of regular files 
//  -1 on error
long fileSize(char *fileName) {
    struct stat sBuf;
    // get the file's stats
    if (stat(fileName, &sBuf) != 0) { // wtf 
        printf(" ERROR: stat of file failed: %d: %s\n", errno, strerror(errno));
        return -1;
    }
    // check that it is a regular file
    if (!S_ISREG(sBuf.st_mode)) {
        printf(" ERROR: stat of file that is not a regular file \n");
        return -1;
    }
    // return the size
    return sBuf.st_size;
}
 
Old 09-29-2010, 04:48 AM   #2
sparker
Member
 
Registered: Aug 2007
Location: Canada
Distribution: OpenBSD 4.6, Debian Lenny
Posts: 64

Rep: Reputation: 16
The source address is stored in the sockaddr struct passed to recvfrom. Using inet_ntoa(srcaddr.sin_addr) you can get the ascii representation of the address.
 
Old 09-29-2010, 12:48 PM   #3
Lantzvillian
Member
 
Registered: Oct 2007
Location: BC, Canada
Distribution: Fedora, Debian
Posts: 210

Original Poster
Rep: Reputation: 41
unfortunately it makes my program segfault. All I added was :

Code:
printf("got something %s\n",inet_ntoa(srcaddr.sin_addr));
after the recv.

Last edited by Lantzvillian; 09-29-2010 at 12:54 PM.
 
Old 09-29-2010, 05:20 PM   #4
sparker
Member
 
Registered: Aug 2007
Location: Canada
Distribution: OpenBSD 4.6, Debian Lenny
Posts: 64

Rep: Reputation: 16
The socklen is wrong Should be sizeof(struct sockaddr_in). Should look something like this:

Code:
socklen_t addrlen = sizeof(struct sockaddr_in);
recvfrom(fd, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&srcaddr, &addrlen);

Last edited by sparker; 09-29-2010 at 05:53 PM.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
doubt in recv() of unix socket prog . wagmare Linux - Networking 4 06-10-2009 11:31 PM
recv() and send() in socket lrios Programming 5 04-23-2008 11:32 AM
recv() function of SOCKET ashucool83 Programming 1 10-08-2005 07:38 PM
function recv() in socket husniteja Programming 1 08-18-2004 09:06 AM
How to receive UDP and ICMP packets, by one UDP socket(PMTUD) myself_rajat Linux - Networking 0 05-28-2004 05:43 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 05:31 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration