sendto() returns values greater than MTU on SOCK_DGRAM (UDP) socket

mic_e picture mic_e · Aug 4, 2012 · Viewed 9.6k times · Source

I'm currently writing a UDP client/server (on GNU/Linux). I'm using sendto() for sending messages on a SOCK_DGRAM socket that has not been bound to a port.

The send(2) manpage states that:

On success, these calls return the number of characters sent. On error, -1 is returned, and errno is set appropriately.

However, sendto always returns its length parameter, indicating success. With messages greater than 65507 (0xFFE3) bytes, it returns a Message too long error.

For messages greater than the MTU of 1500 bytes, the server always receives (via recvfrom()) messages of exactly 1500 bytes, simply cutting the message, without further notice.

(Why) is this behaviour intended, and is there a way of getting notified that something went wrong?

The only workaround I can currently think of would be to simply assume a MTU of 1500 bytes and never send bigger packets.

This is the relevant method:

int udp_send(uint32_t dst, uint16_t port, char *msg, unsigned len) {
    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if(sock < 0) {
            perror("Could not open socket");
            return -1;
    }

    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = htonl(dst);

    int count = sendto(sock, msg, len, 0,
            (struct sockaddr *) &addr, sizeof(addr));
    printf("bytes sent: %d\n", count);

    if(count < 0) {
            perror("Could not send message");
            return -3;
    }

    close(sock);
    return count;
}

A call where the described undesired behaviour occurs would be udp_send(0x7F000001, 1337, bigbuf, 1501); which would return 1501 while sending only 1500 bytes.

Answer

mic_e picture mic_e · Sep 1, 2012

It turns out that, as suggested by nos in his comment, my sending code was actually perfectly fine; my receive code had a simple bug: At some point, I defined its buffer to be just 1500 Bytes in size, and forgot about it later.

Furthermore, I was led by the misconception that GNU/Linux can send UDP packets only to the interface's MTU, which is not true. Even though the standard only guarantess 576 Bytes, at least in my case it seems possible to send (and receive) UDP packets up to 65507 bytes, after which the Message too long error is returned by the sendto() call. The UDP packets are automatically fragmented by the Kernel's IP layer, and re-assembled by the receiver - I did not consider that UDP could be capable of such advanced techniques.