Closed OlegHahm closed 8 years ago
Is #4326 addressing this?
Yes. At least partly.
Does it really make sense to call recvfrom()
without binding to a port first? From my understanding, POSIX sendto()
will choose a random ephemeral port if not bound to a port, but recvfrom()
must know on which port to receive. How else would the network stack know to which application incoming traffic should go to?
Does it really make sense to call recvfrom() without binding to a port first?
Of course it does, how would you implement a client otherwise?
but recvfrom() must know on which port to receive. How else would the network stack know to which application incoming traffic should go to?
You still have the socket struct to identify the "connection".
And what is the intention of not binding before receiving? Letting the system choose a random port for the socket endpoint? How will this port then be announced to other nodes so that they know where to send UDP unicast traffic to? With binding before receiving, the port can at least be configured on all nodes statically.
Of course it does, how would you implement a client otherwise?
A client doesn't recvfrom()
. IMO - and this may be semantics - as soon as you receive, you are a server.
Let A be a UDP server and B a UDP client. A offers a service at the well-known port X. B sends a request to A:X using the sendto()
call. As you said a random ephemeral port Y is used as source port. A identifies the remote peer by the tuple of source address and port, i.e. B:Y. In order to receive the response from A to its initial request, B calls recvfrom()
.
According to http://stackoverflow.com/questions/15861321/how-to-listen-for-udp-datagrams-from-a-certain-host-using-recvfrom and the man pages, one may use connect()
to filter the ports on the receiving side.
Mh, now that @cgundogan is pointing this out I'm wondering these things, too. I thought it was a fuck-up on my part, but then I realized, that interacting with packets without bind only makes sense for sending, but not receiving.
In order to receive the response from A to its initial request, B calls recvfrom().
@OlegHahm but doesn't the sending you described above effectively "binds" the the socket to a port? If not, we don't need a "conn" object for UDP anyway btw, just functions to send and receive.
@OlegHahm but doesn't the sending you described above effectively "binds" the the socket to a port?
That's my understanding, yes, and everything I found on stackoverflow so far (e.g. http://stackoverflow.com/questions/6189831/whats-the-purpose-of-using-sendto-recvfrom-instead-of-connect-send-recv-with-ud or http://stackoverflow.com/questions/8636717/is-it-always-required-to-bind-a-socket) seems to support this.
If not, we don't need a "conn" object for UDP anyway btw, just functions to send and receive.
Couldn't agree more. ;) IMO conn is terribly complex for simple UDP connections.
On windows ( - (: - ) at least it seems necessary to bind a socket to a port before recvfrom
[1]:
s [in]
A descriptor identifying a bound socket.
WSAEINVAL
The socket has not been bound with bind, or an unknown flag was specified, or MSG_OOB was specified for a socket with SO_OOBINLINE enabled, or (for byte stream-style sockets only) len was zero or negative.
[1] https://msdn.microsoft.com/en-us/library/windows/desktop/ms740120%28v=vs.85%29.aspx
"RIOT - if your device is too constrained to run Windows" is a pretty poor punch line in my opinion.
And btw http://msdn.microsoft.com/en-us/library/windows/desktop/ms740120%28v=vs.85%29.aspx states: "Explicit binding is discouraged for client applications. For client applications using this function, the socket can become bound implicitly to a local address through sendto, WSASendTo, or WSAJoinLeaf." and "Note If a socket is opened, a setsockopt call is made, and then a sendto call is made, Windows Sockets performs an implicit bind function call. If the socket is unbound, unique values are assigned to the local association by the system, and the socket is then marked as bound. "
Yes, I can see your point and understand the use case. But isn't this just a little fix going in the direction of adding bind()
to send[to]()
functions if the socket was identified as unbound? This would be the same as binding before receiving (and possible sending in between)
It is however still necessary to bind the socket if you call recvfrom
without any sending in between. And this is the use case I had in mind when reading the title of this issue.
As far as I understand it, calling recvfrom()
without a bind is valid for DGRAM and would result in receiving a datagram received for any port.
This is very hard for me to imagine. I couldn't find any serious sources in the webz that would support this fact. Any application could "hijack/eavesdrop" other applications' udp traffic (without being a RAW socket) if that would be true. I have to test this on my machine before I can believe that..
Maybe this title is more to the point.
Any application could "hijack/eavesdrop" other applications udp traffic (without being a RAW socket) if that would be true.
No, why? If the socket is bound (explicitly by calling bind()
or implicitly by calling sendto()
before) the OS/network stack should deliver these packets to the corresponding socket. If it is not bound, there's nothing to hijack.
I did reuse this code that can be found in [1] to start a udp server. (I created a gist here [2]) I then cut out the bind and all port related stuff from this source file and compiled it.
recvfrom()
does not return with an error, but blocks and waits for an incoming message. I then tried with netcat to send udp traffic to ... I don't know which port? I tried to investigate with ss -s
and ss -lu
. But I couldn't find any fitting port to this application. Netcatting with an arbitrary port would not send a udp datagram to this specific program.
If I call a sendto()
before doing recvfrom()
, I was able to see a port with ss -lu
and send udp datagrams via netcat to it.
So what I learn from this: recvfrom()
does not implicitly bind to a port, but using recvfrom()
without binding explicitly or implicitly doesn't work in terms of receiving datagrams.
[1] https://www.cs.cmu.edu/afs/cs/academic/class/15213-f99/www/class26/udpserver.c [2] https://gist.github.com/cgundogan/25bc8e16d506460d4d98
Would make sense to look into the POSIX standard here, but I guess that's of secondary interest. More important is to allow recvfrom()
with an implicit bind.
More important is to allow recvfrom() with an implicit bind.
Do you mean that recvfrom()
should do the implicit bind? Or were you referring to preceding calls to sendto()
?
I think it doesn't matter so much if sendto()
or recvfrom()
does the actual binding. IMO (and that's why I decided for this option) one can omit the binding if there is no recvfrom()
call. However, binding during sendto()
may tell the OS early on that there might be an application interested in this data. This would matter if we allow, for instance, only one receiver per port.
solved with #4326
If I understand the code and its behavior correctly, it is not possible to call POSIX
recvfrom()
without abind()
before which is not what you would expect for a connectionless (aka DGRAM aka UDP) socket. Or am I missing something?