[haiku-development] Re: UDP bug

  • From: "Axel Dörfler" <axeld@xxxxxxxxxxxxxxxx>
  • To: haiku-development@xxxxxxxxxxxxx
  • Date: Sun, 10 Jan 2010 13:11:55 +0100

Hi Oliver,

Oliver Tappe <zooey@xxxxxxxxxxxxxxx> wrote:
> On 2010-01-09 at 18:36:12 [+0100], Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
> > wrote:
> > when I connect() a UDP socket to a peer in Haiku, no matter if I
> > bound
> > it implicitly or explicitly to INADDR_ANY, it's local address stays
> > bound to INADDR_ANY, whereas it is resolved to a local address in
> > Linux.
> > I would tend to think that our behaviour is indeed wrong, but the
> > documentation I read isn't as explicit about this as I would want
> > it to
> > be.
> Well, I think Stevens' Unix Network Programming Vol I, Chapter 9.11
> is pretty
> explicit when it states that a connected UDP socket receives only
> datagrams
> "destined to the connected socket's local address (IP and port)". I
> think
> this supports your interpretation that we are doing it incorrectly.

Interestingly, we obviously correctly restrict the sender to the
connected address.

> Shall I have a look at it tomorrow, or would you prefer doing that
> yourself?

I already looked into it a bit, but I'm afraid one needs a stack
function for this to work (or otherwise use SIOCGETRT). Feel free to
look into it, if you want to -- if not I could do it, too.

> Anything specific that triggered your question (a testcase)?

I ran into the problem of not knowing the outgoing interface in UDP --
I created a work-around for Haiku via SIOCGETRT, only to later found
out that at least Linux does not support this.
I then read the connect() description again, and it looked like it
would do what I needed, but it didn't work under Haiku. I've attached a
small test application that you can use to reproduce the problem; we
should probably put it into our repository.

Bye,
   Axel.

/*
 * Copyright 2010, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx
 * This file may be used under the terms of the MIT License.
 */


#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>


int
main(int argc, char** argv)
{
        const char* peerAddress = "192.168.0.1";
        if (argc > 1)
                peerAddress = argv[1];

        int fd = socket(AF_INET, SOCK_DGRAM, 0);
        if (fd < 0)
                return 1;

#if 1
        sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = INADDR_ANY;
        addr.sin_port = htons(8888);
        if (bind(fd, (sockaddr*)&addr, sizeof(addr)) != 0)
                perror("bind");

        sockaddr ours;
        socklen_t ourLength = sizeof(sockaddr);
        if (getsockname(fd, &ours, &ourLength) != 0)
                perror("getsockname");
        else {
                printf("After bind: local address %s (%u)\n",
                        inet_ntoa(((sockaddr_in&)ours).sin_addr),
                        ntohs(((sockaddr_in&)ours).sin_port));
        }
#endif

        sockaddr_in peer;
        peer.sin_family = AF_INET;
        peer.sin_addr.s_addr = inet_addr(peerAddress);
        peer.sin_port = htons(8888);
        if (connect(fd, (sockaddr*)&peer, sizeof(peer)) != 0)
                perror("connect");

        ourLength = sizeof(sockaddr);
        if (getsockname(fd, &ours, &ourLength) != 0)
                perror("getsockname");
        else {
                printf("After connect: local address %s (%u)\n",
                        inet_ntoa(((sockaddr_in&)ours).sin_addr),
                        ntohs(((sockaddr_in&)ours).sin_port));
        }

        char buffer[256];
        if (argc > 2 && !strcmp(argv[2], "recv")) {
                ssize_t bytesReceived = recv(fd, buffer, sizeof(buffer), 0);
                if (bytesReceived > 0) {
                        buffer[bytesReceived] = 0;
                        printf("received: %s\n", buffer);
                } else
                        perror("recv");
        } else {
                if (argc > 2)
                        send(fd, argv[2], strlen(argv[2]), 0);

                fgets(buffer, sizeof(buffer), stdin);
        }

        close(fd);
        return 0;
}


Other related posts: