Since 2015, Linux has introduced a new socket option to overcome TCP
limitations: When an application needs to force a source IP on an active
TCP socket it has to use bind(IP, port=x). As most applications do not
want to deal with already used ports, x is often set to 0, meaning the
kernel is in charge to find an available port. But kernel does not know
yet if this socket is going to be a listener or be connected. This
IP_BIND_ADDRESS_NO_PORT socket option ask the kernel to ignore the 0
port provided by application in bind(IP, port=0) and only remember the
given IP address. The port will be automatically chosen at connect()
time, in a way that allows sharing a source port as long as the 4-tuples
are unique.
Enable IP_BIND_ADDRESS_NO_PORT on the outgoing TCP sockets to overcome
this TCP limitation.
* Use minimum MTU on IPv6 sockets
*/
+isc_result_t
+isc__nm_tcp_bind_no_port(uv_tcp_t *handle);
+/*%<
+ * Set IP_BIND_ADDRESS_NO_PORT on the socket (Linux only).
+ */
+
void
isc__nm_set_network_buffers(uv_handle_t *handle);
/*%>
return ISC_R_SUCCESS;
}
+
+isc_result_t
+isc__nm_tcp_bind_no_port(uv_tcp_t *handle ISC_ATTR_UNUSED) {
+#ifdef IP_BIND_ADDRESS_NO_PORT
+ uv_os_sock_t fd = -1;
+
+ int r = uv_fileno((const uv_handle_t *)handle, (uv_os_fd_t *)&fd);
+ if (r < 0) {
+ return ISC_R_FAILURE;
+ }
+
+ if (setsockopt_on(fd, IPPROTO_IP, IP_BIND_ADDRESS_NO_PORT) == -1) {
+ return ISC_R_FAILURE;
+ }
+#endif
+ return ISC_R_SUCCESS;
+}
}
isc__nm_incstats(sock, STATID_OPEN);
+ isc__nm_tcp_bind_no_port(&sock->uv_handle.tcp);
+
if (req->local.length != 0) {
r = uv_tcp_bind(&sock->uv_handle.tcp, &req->local.type.sa, 0);
if (r != 0) {