This works fine:
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 4
setsockopt(4, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
bind(4, {sa_family=AF_INET, sin_port=htons(4444), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
connect(4, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("1.1.1.1")}, 16) = 0
And we can observe the proper binding to local and remote:
$ sudo lsof -Pni :4444
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
udpdup 2815 nhed 4u IPv4 126724 0t0 UDP 10.0.2.15:4444->1.1.1.1:*
But putting the connect first, get an error on the bind, why?
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 4
setsockopt(4, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
connect(4, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("1.1.1.1")}, 16) = 0
bind(4, {sa_family=AF_INET, sin_port=htons(4444), sin_addr=inet_addr("0.0.0.0")}, 16) = -1 EINVAL (Invalid argument)
Why do I care you ask?
I thought that received packets are matched against a 5-element tuple (proto, loc addr, loc port, rem addr, rem port). Where some of the 5 can be ANY (a wildcard), indicated numerically as 0
or 0.0.0.0
in struct sockaddr_in
and often represented often in netstat
, lsof
, etc. The above lsof
output shows 4/5 elements specified, remote port left as wildcard)
I could not remember if multiple sockets should exists where some had the wildcard peer addr and others could be explicit, sending traffic to the right port based on a best match.
I wanted to experiment and check that when one app has bound a port without specifying the sender address, that another app could connect & bind the peer, to form a more complete tuple.
[note that the first app does not specify SO_REUSEADDR
]
p.s. could someone with enough points please create a udp-connect
tag? (and even a udp-bind)
connect(2)
implicitly binds your local port, so subsequent explicit bind(2)
fails.
You can bind multiple sockets to the same local port, but all the bindings following the first one must be more specific. Say, first socket is bound to INADDR_ANY
, and others are to specific addresses of existing network interfaces. Note, that all the sockets must be set with SO_REUSEADDR
.
Then there's multicast, which allows you to create completely duplicate socket bindings, but only to a specific class of addresses, and you have to do a bit more work to set it up.
It also seems to me you are confusing this with TCP listening vs. connected sockets.
connect(2)
also fixes socket local address according to the route to destination.