Browse Source

[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.
Tetralux 1 year ago
parent
commit
ec0831da70
2 changed files with 12 additions and 3 deletions
  1. 4 2
      core/net/errors_darwin.odin
  2. 8 1
      core/net/socket_darwin.odin

+ 4 - 2
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.

+ 8 - 1
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
 }