-1

I am using sendto() function in C. I have set the destination address and dest port. While sending UDP frames I can see the frames in Wireshark and the number of packet Wireshark shows are exactly as I have defined in my program.

The problem is even though the destination address is not reachable the frames are being sent and I can see it in Wireshark.

Should not the sendto() function generates a error if the destination IP is not existing?

 if (sendto(sockfd, &buffer[i], UDP_FRAME, 0,
                    (const struct sockaddr*)&server, sizeof(server)) < 0)
        {
            fprintf(stderr, "Error in sendto()\n");
            //return EXIT_FAILURE;
        }

Dest. IP: 234.168.0.1 Dest port: 80 or 9 (discard protocol)

    #define PORT (80)
    #define FRAMES (20000)
    #define UDP_FRAME (1442)
    #define SERVERADDRESS "234.168.0.1"
    #define BUFFER_SIZE (FRAMES * UDP_FRAME)
    char buffer[BUFFER_SIZE];

    int main(int argc, char **argv)
{
    struct timespec start, end, loop_start, loop_end;
    int sockfd, count_frame = 0, frames_total, i = UDP_FRAME, n=1;
    struct sockaddr_in server;

    printf("Build Data...\n");
    build(buffer, sizeof(buffer));

    printf("Configure socket...\n");
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
    {
        fprintf(stderr, "Error opening socket");
        return EXIT_FAILURE;
    }

    /*----------------------------------------------------*/
/*---       Initialize address protocol            ---*/
/*----------------------------------------------------*/

    bzero((char*)&server, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = inet_addr(SERVERADDRESS);
    server.sin_port = htons(PORT);

    /*---------------------------------------------------*/
/*---       S E N D I N G   D A T A        --*/
/*---------------------------------------------------*/

    printf("\nSend UDP data...\n\n");
    clock_gettime(CLOCK_MONOTONIC_RAW, &start);
    clock_gettime(CLOCK_MONOTONIC_RAW, &loop_start);
    frames_total = 0;

    for (int i = 0; i < BUFFER_SIZE; i += UDP_FRAME) {
    //while(1) {    

        if (sendto(sockfd, &buffer[i], UDP_FRAME, 0,
                    (const struct sockaddr*)&server, sizeof(server)) < 0)
        {
            fprintf(stderr, "Error in sendto()\n");
            //return EXIT_FAILURE;
        }
    count_frame += 1;

    clock_gettime(CLOCK_MONOTONIC_RAW, &loop_end);
    if ((loop_end.tv_nsec - loop_start.tv_nsec) > 5000000) {
        printf("\nCount [%d] ... ", n);
        printf("Fames sent: %d\n", count_frame);
        frames_total += count_frame;
        n+=1;
        count_frame = 0;
        clock_gettime(CLOCK_MONOTONIC_RAW, &loop_start);
    }

    }
    printf("Total successful counted frames: %d \n", frames_total);

    return EXIT_SUCCESS;
}
alk
  • 69,737
  • 10
  • 105
  • 255
  • Please try to create a [Minimal, Complete, and Verifiable Example](http://stackoverflow.com/help/mcve) to show us. Also, are you 100% sure that the address does not exist anywhere on the Internet? – Some programmer dude Oct 19 '18 at 11:52
  • @PaulOgilvie No, UDP datagram communication is (normally) unconnected, and you need to explicitly specify the destination host, and that can only be done through `sendto` (which is very different from `send`). – Some programmer dude Oct 19 '18 at 11:56
  • @Someprogrammerdude I have added the code to the question with some functions and lines skipped. – Nazmul Hossain Rakib Oct 19 '18 at 12:00
  • 1
    That looks okay. So the problem could just be the usual problems with UDP: It's *unreliable*. There's a lot of conditions that could cause the datagrams to be dropped without any errors. If you need verification that a datagram arrived you need to create a protocol on top of UDP, for example including sequence numbering and acknowledge messages. Then using timeouts you could retransmit or consider the packet (and the "connection") lost. – Some programmer dude Oct 19 '18 at 12:05
  • @Someprogrammerdude You answer makes sense. It will help I think. – Nazmul Hossain Rakib Oct 19 '18 at 12:10

2 Answers2

1

sendto() will give you an error if the host doesn't know a route to the host (which is almost never the case, since your host will have a default gateway). Otherwise, you might (or might not) receive an ICMP destination unreachable message if your packet did not reach the targeted application, but this is unreliable and won't be communicated by the call to sendto().

What you can do is to query the socket with

struct sock_extended_err err;
socklen_t errlen = sizeof(err);
getsockopt(fd, SOL_IP, IP_RECVERR, &err, &errlen);

for received errors, which will give you detailed information about received errors on the socket (i.e. ICMP port unreachable, ICMP host unreachable, etc. pp). This can help, but as I said, it is not realiable, since ICMP messages are often strictly rate limited, filtered on the way or not sent at all, if your packet is blocked by a packet filter (firewall).

Ctx
  • 18,090
  • 24
  • 36
  • 51
1

UDP is an unreliable protocol. A call to sendto is successful once the packet leaves the interface. After that, whether it gets to its destination or not is up to the network.

Even if the network supports ICMP messages stating that the host or port is not reachable, it won't matter in your particular case because you're sending to a multicast address. If you have at least one multicast-capable interface, the system will pick one to send the packet over. It could be received by multiple (or no) hosts. So it doesn't make sense to say that the destination is not reachable.

dbush
  • 205,898
  • 23
  • 218
  • 273