From ec0831da706f696ce6b65e3ac2108179902f0d38 Mon Sep 17 00:00:00 2001 From: Tetralux Date: Thu, 22 Feb 2024 14:41:37 +0000 Subject: [PATCH 1/2] [net] Better error code for binding a privileged port without root access on Darwin This condition results in os.EACCESS, which we were translating to Broadcast_Disabled. This was the case because binding to the broadcast address on a UDP port, without setting the BROADCAST flag, also results in this error. Given the fact that reserved ports also produce this error, we now check for this condition in net.bind() and translate it to a custom, clearer error: Privileged_Port_Without_Root. --- core/net/errors_darwin.odin | 6 ++++-- core/net/socket_darwin.odin | 9 ++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/core/net/errors_darwin.odin b/core/net/errors_darwin.odin index c80d2cf56..3116af0ab 100644 --- a/core/net/errors_darwin.odin +++ b/core/net/errors_darwin.odin @@ -34,7 +34,7 @@ Create_Socket_Error :: enum c.int { Dial_Error :: enum c.int { None = 0, - Port_Required = -1, + Port_Required = -1, // Attempted to dial an endpointing without a port being set. Address_In_Use = c.int(os.EADDRINUSE), In_Progress = c.int(os.EINPROGRESS), @@ -54,7 +54,9 @@ Dial_Error :: enum c.int { } Bind_Error :: enum c.int { - None = 0, + None = 0, + Privileged_Port_Without_Root = -1, // Attempted to bind to a port less than 1024 without root access. + Address_In_Use = c.int(os.EADDRINUSE), // Another application is currently bound to this endpoint. Given_Nonlocal_Address = c.int(os.EADDRNOTAVAIL), // The address is not a local address on this machine. Broadcast_Disabled = c.int(os.EACCES), // To bind a UDP socket to the broadcast address, the appropriate socket option must be set. diff --git a/core/net/socket_darwin.odin b/core/net/socket_darwin.odin index 2585d134b..2bc7ff9bd 100644 --- a/core/net/socket_darwin.odin +++ b/core/net/socket_darwin.odin @@ -92,13 +92,20 @@ _dial_tcp_from_endpoint :: proc(endpoint: Endpoint, options := default_tcp_optio return } +// On Darwin, any port below 1024 is 'privileged' - which means that you need root access in order to use it. +MAX_PRIVILEGED_PORT :: 1023 + @(private) _bind :: proc(skt: Any_Socket, ep: Endpoint) -> (err: Network_Error) { sockaddr := _endpoint_to_sockaddr(ep) s := any_socket_to_socket(skt) res := os.bind(os.Socket(s), (^os.SOCKADDR)(&sockaddr), i32(sockaddr.len)) if res != os.ERROR_NONE { - err = Bind_Error(res) + if res == os.EACCES && ep.port <= MAX_PRIVILEGED_PORT { + err = .Port_Reserved + } else { + err = Bind_Error(res) + } } return } From d74ddb2d913888d0d41626eb079d923b42a2ad0f Mon Sep 17 00:00:00 2001 From: Tetralux Date: Thu, 22 Feb 2024 15:01:55 +0000 Subject: [PATCH 2/2] fixup --- core/net/socket_darwin.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/net/socket_darwin.odin b/core/net/socket_darwin.odin index 2bc7ff9bd..ba86f1005 100644 --- a/core/net/socket_darwin.odin +++ b/core/net/socket_darwin.odin @@ -102,7 +102,7 @@ _bind :: proc(skt: Any_Socket, ep: Endpoint) -> (err: Network_Error) { res := os.bind(os.Socket(s), (^os.SOCKADDR)(&sockaddr), i32(sockaddr.len)) if res != os.ERROR_NONE { if res == os.EACCES && ep.port <= MAX_PRIVILEGED_PORT { - err = .Port_Reserved + err = .Privileged_Port_Without_Root } else { err = Bind_Error(res) }