Browse Source

Port `core:net` to FreeBSD

Feoramund 1 year ago
parent
commit
e61d893a74

+ 2 - 2
core/net/addr.odin

@@ -1,4 +1,4 @@
-// +build windows, linux, darwin
+// +build windows, linux, darwin, freebsd
 package net
 package net
 
 
 /*
 /*
@@ -743,4 +743,4 @@ parse_ip_component :: proc(input: string, max_value := u64(max(u32)), bases := D
 get_network_interfaces :: proc() -> []Address {
 get_network_interfaces :: proc() -> []Address {
 	// TODO: Implement using `enumerate_interfaces` and returning only the addresses of active interfaces.
 	// TODO: Implement using `enumerate_interfaces` and returning only the addresses of active interfaces.
 	return nil
 	return nil
-}
+}

+ 2 - 2
core/net/common.odin

@@ -1,4 +1,4 @@
-// +build windows, linux, darwin
+// +build windows, linux, darwin, freebsd
 package net
 package net
 
 
 /*
 /*
@@ -413,4 +413,4 @@ DNS_Record_Header :: struct #packed {
 DNS_Host_Entry :: struct {
 DNS_Host_Entry :: struct {
 	name: string,
 	name: string,
 	addr: Address,
 	addr: Address,
-}
+}

+ 2 - 2
core/net/dns.odin

@@ -1,4 +1,4 @@
-// +build windows, linux, darwin
+// +build windows, linux, darwin, freebsd
 package net
 package net
 
 
 /*
 /*
@@ -30,7 +30,7 @@ when ODIN_OS == .Windows {
 		resolv_conf        = "",
 		resolv_conf        = "",
 		hosts_file         = "%WINDIR%\\system32\\drivers\\etc\\hosts",
 		hosts_file         = "%WINDIR%\\system32\\drivers\\etc\\hosts",
 	}
 	}
-} else when ODIN_OS == .Linux || ODIN_OS == .Darwin || ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD {
+} else when ODIN_OS == .Linux || ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD {
 	DEFAULT_DNS_CONFIGURATION :: DNS_Configuration{
 	DEFAULT_DNS_CONFIGURATION :: DNS_Configuration{
 		resolv_conf        = "/etc/resolv.conf",
 		resolv_conf        = "/etc/resolv.conf",
 		hosts_file         = "/etc/hosts",
 		hosts_file         = "/etc/hosts",

+ 1 - 1
core/net/dns_unix.odin

@@ -1,4 +1,4 @@
-//+build linux, darwin
+//+build linux, darwin, freebsd
 package net
 package net
 /*
 /*
 	Package net implements cross-platform Berkeley Sockets, DNS resolution and associated procedures.
 	Package net implements cross-platform Berkeley Sockets, DNS resolution and associated procedures.

+ 191 - 0
core/net/errors_freebsd.odin

@@ -0,0 +1,191 @@
+//+build freebsd
+package net
+
+import "core:c"
+import "core:sys/freebsd"
+
+Create_Socket_Error :: enum c.int {
+	None                                 = 0,
+	Access_Denied                        = cast(c.int)freebsd.Errno.EACCES,
+	Family_Not_Supported_For_This_Socket = cast(c.int)freebsd.Errno.EAFNOSUPPORT,
+	Full_Per_Process_Descriptor_Table    = cast(c.int)freebsd.Errno.EMFILE,
+	Full_System_File_Table               = cast(c.int)freebsd.Errno.ENFILE,
+	Insufficient_Buffer_Space            = cast(c.int)freebsd.Errno.ENOBUFS,
+	Insufficient_Permission              = cast(c.int)freebsd.Errno.EPERM,
+	Protocol_Unsupported_In_Family       = cast(c.int)freebsd.Errno.EPROTONOSUPPORT,
+	Socket_Type_Unsupported_By_Protocol  = cast(c.int)freebsd.Errno.EPROTOTYPE,
+}
+
+Dial_Error :: enum c.int {
+	None                        = 0,
+	Port_Required               = -1,
+	Not_Descriptor              = cast(c.int)freebsd.Errno.EBADF,
+	Invalid_Namelen             = cast(c.int)freebsd.Errno.EINVAL,
+	Not_Socket                  = cast(c.int)freebsd.Errno.ENOTSOCK,
+	Address_Unavailable         = cast(c.int)freebsd.Errno.EADDRNOTAVAIL,
+	Wrong_Family_For_Socket     = cast(c.int)freebsd.Errno.EAFNOSUPPORT,
+	Already_Connected           = cast(c.int)freebsd.Errno.EISCONN,
+	Timeout                     = cast(c.int)freebsd.Errno.ETIMEDOUT,
+	Refused_By_Remote_Host      = cast(c.int)freebsd.Errno.ECONNREFUSED,
+	// `Refused` alias for core:net tests.
+	Refused                     = cast(c.int)freebsd.Errno.ECONNREFUSED,
+	Reset_By_Remote_Host        = cast(c.int)freebsd.Errno.ECONNRESET,
+	Network_Unreachable         = cast(c.int)freebsd.Errno.ENETUNREACH,
+	Host_Unreachable            = cast(c.int)freebsd.Errno.EHOSTUNREACH,
+	Address_In_Use              = cast(c.int)freebsd.Errno.EADDRINUSE,
+	Invalid_Address_Space       = cast(c.int)freebsd.Errno.EFAULT,
+	In_Progress                 = cast(c.int)freebsd.Errno.EINPROGRESS,
+	Interrupted_By_Signal       = cast(c.int)freebsd.Errno.EINTR,
+	Previous_Attempt_Incomplete = cast(c.int)freebsd.Errno.EALREADY,
+	Broadcast_Unavailable       = cast(c.int)freebsd.Errno.EACCES,
+	Auto_Port_Unavailable       = cast(c.int)freebsd.Errno.EAGAIN,
+
+	// NOTE: There are additional connect() error possibilities, but they are
+	// strictly for addresses in the UNIX domain.
+}
+
+Bind_Error :: enum c.int {
+	None                         = 0,
+	Kernel_Resources_Unavailable = cast(c.int)freebsd.Errno.EAGAIN,
+	Not_Descriptor               = cast(c.int)freebsd.Errno.EBADF,
+
+	// NOTE: bind() can also return EINVAL if the underlying `addrlen` is an
+	// invalid length for the address family. This shouldn't happen for the net
+	// package, but it's worth noting.
+	Already_Bound                = cast(c.int)freebsd.Errno.EINVAL,
+	Not_Socket                   = cast(c.int)freebsd.Errno.ENOTSOCK,
+	Given_Nonlocal_Address       = cast(c.int)freebsd.Errno.EADDRNOTAVAIL,
+	Address_In_Use               = cast(c.int)freebsd.Errno.EADDRINUSE,
+	Address_Family_Mismatch      = cast(c.int)freebsd.Errno.EAFNOSUPPORT,
+	Protected_Address            = cast(c.int)freebsd.Errno.EACCES,
+	Invalid_Address_Space        = cast(c.int)freebsd.Errno.EFAULT,
+
+	// NOTE: There are additional bind() error possibilities, but they are
+	// strictly for addresses in the UNIX domain.
+}
+
+Listen_Error :: enum c.int {
+	None                                    = 0,
+	Not_Descriptor                          = cast(c.int)freebsd.Errno.EBADF,
+	Socket_Not_Bound                        = cast(c.int)freebsd.Errno.EDESTADDRREQ,
+	Already_Connected                       = cast(c.int)freebsd.Errno.EINVAL,
+	Not_Socket                              = cast(c.int)freebsd.Errno.ENOTSOCK,
+	Listening_Not_Supported_For_This_Socket = cast(c.int)freebsd.Errno.EOPNOTSUPP,
+}
+
+Accept_Error :: enum c.int {
+	None                              = 0,
+	Not_Descriptor                    = cast(c.int)freebsd.Errno.EBADF,
+	Interrupted                       = cast(c.int)freebsd.Errno.EINTR,
+	Full_Per_Process_Descriptor_Table = cast(c.int)freebsd.Errno.EMFILE,
+	Full_System_File_Table            = cast(c.int)freebsd.Errno.ENFILE,
+	Not_Socket                        = cast(c.int)freebsd.Errno.ENOTSOCK,
+	Listen_Not_Called_On_Socket_Yet   = cast(c.int)freebsd.Errno.EINVAL,
+	Address_Not_Writable              = cast(c.int)freebsd.Errno.EFAULT,
+
+	// NOTE: This is the same as EWOULDBLOCK.
+	No_Connections_Available          = cast(c.int)freebsd.Errno.EAGAIN,
+
+	New_Connection_Aborted            = cast(c.int)freebsd.Errno.ECONNABORTED,
+}
+
+TCP_Recv_Error :: enum c.int {
+	None                                 = 0,
+	Not_Descriptor                       = cast(c.int)freebsd.Errno.EBADF,
+	Connection_Closed                    = cast(c.int)freebsd.Errno.ECONNRESET,
+	Not_Connected                        = cast(c.int)freebsd.Errno.ENOTCONN,
+	Not_Socket                           = cast(c.int)freebsd.Errno.ENOTSOCK,
+
+	// NOTE(Feoramund): The next two errors are only relevant for recvmsg(),
+	// but I'm including them for completeness's sake.
+	Full_Table_And_Pending_Data          = cast(c.int)freebsd.Errno.EMFILE,
+	Invalid_Message_Size                 = cast(c.int)freebsd.Errno.EMSGSIZE,
+
+	Timeout                              = cast(c.int)freebsd.Errno.EAGAIN,
+	Interrupted_By_Signal                = cast(c.int)freebsd.Errno.EINTR,
+	Buffer_Pointer_Outside_Address_Space = cast(c.int)freebsd.Errno.EFAULT,
+}
+
+UDP_Recv_Error :: enum c.int {
+	None                                 = 0,
+	Not_Descriptor                       = cast(c.int)freebsd.Errno.EBADF,
+	Connection_Closed                    = cast(c.int)freebsd.Errno.ECONNRESET,
+	Not_Connected                        = cast(c.int)freebsd.Errno.ENOTCONN,
+	Not_Socket                           = cast(c.int)freebsd.Errno.ENOTSOCK,
+
+	// NOTE(Feoramund): The next two errors are only relevant for recvmsg(),
+	// but I'm including them for completeness's sake.
+	Full_Table_And_Data_Discarded        = cast(c.int)freebsd.Errno.EMFILE,
+	Invalid_Message_Size                 = cast(c.int)freebsd.Errno.EMSGSIZE,
+
+	Timeout                              = cast(c.int)freebsd.Errno.EAGAIN,
+	Interrupted_By_Signal                = cast(c.int)freebsd.Errno.EINTR,
+	Buffer_Pointer_Outside_Address_Space = cast(c.int)freebsd.Errno.EFAULT,
+}
+
+TCP_Send_Error :: enum c.int {
+	None                              = 0,
+	Not_Descriptor                    = cast(c.int)freebsd.Errno.EBADF,
+	Broadcast_Status_Mismatch         = cast(c.int)freebsd.Errno.EACCES,
+	Not_Connected                     = cast(c.int)freebsd.Errno.ENOTCONN,
+	Not_Socket                        = cast(c.int)freebsd.Errno.ENOTSOCK,
+	Argument_In_Invalid_Address_Space = cast(c.int)freebsd.Errno.EFAULT,
+
+	Message_Size_Breaks_Atomicity     = cast(c.int)freebsd.Errno.EMSGSIZE,
+
+	/* The socket is marked non-blocking, or MSG_DONTWAIT is
+	   specified, and the requested operation would block. */
+	Would_Block                       = cast(c.int)freebsd.Errno.EAGAIN,
+
+	// NOTE: This error arises for two distinct reasons.
+	/* The system was unable to allocate an internal buffer.
+	   The operation may succeed when buffers become available. */
+
+	/* The output queue for a network interface was full.
+	   This generally indicates that the interface has stopped
+	   sending, but may be caused by transient congestion. */
+	No_Buffer_Space_Available         = cast(c.int)freebsd.Errno.ENOBUFS,
+
+	Host_Unreachable                  = cast(c.int)freebsd.Errno.EHOSTUNREACH,
+	Already_Connected                 = cast(c.int)freebsd.Errno.EISCONN,
+	ICMP_Unreachable                  = cast(c.int)freebsd.Errno.ECONNREFUSED,
+	Host_Down                         = cast(c.int)freebsd.Errno.EHOSTDOWN,
+	Network_Down                      = cast(c.int)freebsd.Errno.ENETDOWN,
+	Jailed_Socket_Tried_To_Escape     = cast(c.int)freebsd.Errno.EADDRNOTAVAIL,
+	Cannot_Send_More_Data             = cast(c.int)freebsd.Errno.EPIPE,
+}
+
+// NOTE(Feoramund): The same as TCP errors go, as far as I'm aware.
+UDP_Send_Error :: distinct TCP_Send_Error
+
+Shutdown_Manner :: enum c.int {
+	Receive = cast(c.int)freebsd.Shutdown_Method.RD,
+	Send    = cast(c.int)freebsd.Shutdown_Method.WR,
+	Both    = cast(c.int)freebsd.Shutdown_Method.RDWR,
+}
+
+Shutdown_Error :: enum c.int {
+	None           = 0,
+	Not_Descriptor = cast(c.int)freebsd.Errno.EBADF,
+	Invalid_Manner = cast(c.int)freebsd.Errno.EINVAL,
+	Not_Connected  = cast(c.int)freebsd.Errno.ENOTCONN,
+	Not_Socket     = cast(c.int)freebsd.Errno.ENOTSOCK,
+}
+
+Socket_Option_Error :: enum c.int {
+	None                                                 = 0,
+	Value_Out_Of_Range                                   = -1,
+	Not_Descriptor                                       = cast(c.int)freebsd.Errno.EBADF,
+	Not_Socket                                           = cast(c.int)freebsd.Errno.ENOTSOCK,
+	Unknown_Option_For_Level                             = cast(c.int)freebsd.Errno.ENOPROTOOPT,
+	Argument_In_Invalid_Address_Space                    = cast(c.int)freebsd.Errno.EFAULT,
+	Cannot_Install_Accept_Filter_On_Non_Listening_Socket = cast(c.int)freebsd.Errno.EINVAL,
+	System_Memory_Allocation_Failed                      = cast(c.int)freebsd.Errno.ENOMEM,
+	Insufficient_System_Resources                        = cast(c.int)freebsd.Errno.ENOBUFS,
+}
+
+Set_Blocking_Error :: enum c.int {
+	None             = 0,
+	Not_Descriptor   = cast(c.int)freebsd.Errno.EBADF,
+	Wrong_Descriptor = cast(c.int)freebsd.Errno.ENOTTY,
+}

+ 1 - 1
core/net/interface.odin

@@ -1,4 +1,4 @@
-// +build windows, linux, darwin
+// +build windows, linux, darwin, freebsd
 package net
 package net
 
 
 /*
 /*

+ 158 - 0
core/net/interface_freebsd.odin

@@ -0,0 +1,158 @@
+//+build freebsd
+package net
+
+import "core:c"
+import "core:strings"
+import "core:sys/freebsd"
+
+@(private)
+_enumerate_interfaces :: proc(allocator := context.allocator) -> (interfaces: []Network_Interface, err: Network_Error) {
+	// This is a simplified implementation of `getifaddrs` from the FreeBSD
+	// libc using only Odin and syscalls.
+	context.allocator = allocator
+
+	mib := [6]freebsd.MIB_Identifier {
+		.CTL_NET,
+		cast(freebsd.MIB_Identifier)freebsd.Protocol_Family.ROUTE,
+		freebsd.MIB_Identifier(0),
+		freebsd.MIB_Identifier(0),
+		.NET_RT_IFLISTL,
+		freebsd.MIB_Identifier(0),
+	}
+
+	// Figure out how much space we need.
+	needed: c.size_t = ---
+
+	errno := freebsd.sysctl(mib[:], nil, &needed, nil, 0)
+	if errno != nil {
+		return nil, .Unable_To_Enumerate_Network_Interfaces
+	}
+
+	// Allocate and get the entries.
+	buf, alloc_err := make([]byte, needed)
+	if alloc_err != nil {
+		return nil, .Unable_To_Enumerate_Network_Interfaces
+	}
+	defer delete(buf)
+
+	errno = freebsd.sysctl(mib[:], &buf[0], &needed, nil, 0)
+	if errno != nil {
+		return nil, .Unable_To_Enumerate_Network_Interfaces
+	}
+
+	// Build the interfaces with each message.
+	if_builder: [dynamic]Network_Interface
+	for message_pointer: uintptr = 0; message_pointer < cast(uintptr)needed; /**/ {
+		rtm := cast(^freebsd.Route_Message_Header)&buf[message_pointer]
+		if rtm.version != freebsd.RTM_VERSION {
+			continue
+		}
+
+		#partial switch rtm.type {
+		case .IFINFO:
+			ifm := cast(^freebsd.Interface_Message_Header_Len)&buf[message_pointer]
+			if .IFP not_in ifm.addrs {
+				// No name available.
+				break
+			}
+
+			dl := cast(^freebsd.Socket_Address_Data_Link)&buf[message_pointer + cast(uintptr)ifm.len]
+
+			if_data := cast(^freebsd.Interface_Data)&buf[message_pointer + cast(uintptr)ifm.data_off]
+
+			// This is done this way so the different message types can
+			// dynamically build a `Network_Interface`.
+			resize(&if_builder, max(len(if_builder), 1 + cast(int)ifm.index))
+			interface := if_builder[ifm.index]
+
+			interface.adapter_name = strings.clone_from_bytes(dl.data[0:dl.nlen])
+			interface.mtu = if_data.mtu
+
+			switch if_data.link_state {
+			case .UNKNOWN: /* Do nothing; the default value is valid. */
+			case .UP:   interface.link.state |= { .Up   }
+			case .DOWN: interface.link.state |= { .Down }
+			}
+
+			// TODO: Uncertain if these are equivalent:
+			// interface.link.transmit_speed = if_data.baudrate
+			// interface.link.receive_speed = if_data.baudrate
+
+			if dl.type == .LOOP {
+				interface.link.state |= { .Loopback }
+			} else {
+				interface.physical_address = physical_address_to_string(dl.data[dl.nlen:][:6])
+			}
+
+			if_builder[ifm.index] = interface
+
+		case .NEWADDR:
+			RTA_MASKS :: freebsd.Route_Address_Flags { .IFA, .NETMASK }
+			ifam := cast(^freebsd.Interface_Address_Message_Header_Len)&buf[message_pointer]
+			if ifam.addrs & RTA_MASKS == {} {
+				break
+			}
+
+			resize(&if_builder, max(len(if_builder), 1 + cast(int)ifam.index))
+			interface := if_builder[ifam.index]
+
+			address_pointer := message_pointer + cast(uintptr)ifam.len
+
+			lease: Lease
+			address_set: bool
+			for address_type in ifam.addrs {
+				ptr := cast(^freebsd.Socket_Address_Basic)&buf[address_pointer]
+
+				#partial switch address_type {
+				case .IFA:
+					#partial switch ptr.family {
+					case .INET:
+						real := cast(^freebsd.Socket_Address_Internet)ptr
+						lease.address = cast(IP4_Address)real.addr.addr8
+						address_set = true
+					case .INET6:
+						real := cast(^freebsd.Socket_Address_Internet6)ptr
+						lease.address = cast(IP6_Address)real.addr.addr16
+						address_set = true
+					}
+				case .NETMASK:
+					#partial switch ptr.family {
+					case .INET:
+						real := cast(^freebsd.Socket_Address_Internet)ptr
+						lease.netmask = cast(Netmask)cast(IP4_Address)real.addr.addr8
+					case .INET6:
+						real := cast(^freebsd.Socket_Address_Internet6)ptr
+						lease.netmask = cast(Netmask)cast(IP6_Address)real.addr.addr16
+					}
+				}
+
+				SALIGN : u8 : size_of(c.long) - 1
+				address_advance: uintptr = ---
+				if ptr.len > 0 {
+					address_advance = cast(uintptr)((ptr.len + SALIGN) & ~SALIGN)
+				} else {
+					address_advance = cast(uintptr)(SALIGN + 1)
+				}
+
+				address_pointer += address_advance
+			}
+
+			if address_set {
+				append(&interface.unicast, lease)
+			}
+
+			if_builder[ifam.index] = interface
+		}
+
+		message_pointer += cast(uintptr)rtm.msglen
+	}
+
+	// Remove any interfaces that were allocated but had no name.
+	#no_bounds_check for i := len(if_builder) - 1; i >= 0; i -= 1 {
+		if len(if_builder[i].adapter_name) == 0 {
+			ordered_remove(&if_builder, i)
+		}
+	}
+
+	return if_builder[:], nil
+}

+ 1 - 1
core/net/socket.odin

@@ -1,4 +1,4 @@
-// +build windows, linux, darwin
+// +build windows, linux, darwin, freebsd
 package net
 package net
 
 
 /*
 /*

+ 365 - 0
core/net/socket_freebsd.odin

@@ -0,0 +1,365 @@
+//+build freebsd
+package net
+
+import "core:c"
+import "core:sys/freebsd"
+import "core:time"
+
+Fd :: freebsd.Fd
+
+Socket_Option :: enum c.int {
+	// TODO: Test and implement more socket options.
+	// DEBUG
+	// ACCEPTCONN
+	Reuse_Address             = cast(c.int)freebsd.Socket_Option.REUSEADDR,
+	Keep_Alive                = cast(c.int)freebsd.Socket_Option.KEEPALIVE,
+	// DONTROUTE
+	Broadcast                 = cast(c.int)freebsd.Socket_Option.BROADCAST,
+	Use_Loopback              = cast(c.int)freebsd.Socket_Option.USELOOPBACK,
+	Linger                    = cast(c.int)freebsd.Socket_Option.LINGER,
+	Out_Of_Bounds_Data_Inline = cast(c.int)freebsd.Socket_Option.OOBINLINE,
+	// REUSEPORT
+	// TIMESTAMP
+	// NOSIGPIPE
+	// ACCEPTFILTER
+	// BINTIME
+	// NO_OFFLOAD
+	// NO_DDP
+	// REUSEPORT_LB
+	// RERROR
+
+	Send_Buffer_Size          = cast(c.int)freebsd.Socket_Option.SNDBUF,
+	Receive_Buffer_Size       = cast(c.int)freebsd.Socket_Option.RCVBUF,
+	// SNDLOWAT
+	// RCVLOWAT
+	Send_Timeout              = cast(c.int)freebsd.Socket_Option.SNDTIMEO,
+	Receive_Timeout           = cast(c.int)freebsd.Socket_Option.RCVTIMEO,
+}
+
+@(private)
+_create_socket :: proc(family: Address_Family, protocol: Socket_Protocol) -> (socket: Any_Socket, err: Network_Error) {
+	sys_family:      freebsd.Protocol_Family = ---
+	sys_protocol:    freebsd.Protocol        = ---
+	sys_socket_type: freebsd.Socket_Type     = ---
+
+	switch family {
+	case .IP4: sys_family = .INET
+	case .IP6: sys_family = .INET6
+	}
+
+	switch protocol {
+	case .TCP: sys_protocol = .TCP; sys_socket_type = .STREAM
+	case .UDP: sys_protocol = .UDP; sys_socket_type = .DGRAM
+	}
+
+	new_socket, errno := freebsd.socket(sys_family, sys_socket_type, sys_protocol)
+	if errno != nil {
+		err = cast(Create_Socket_Error)errno
+		return
+	}
+
+	switch protocol {
+	case .TCP: return cast(TCP_Socket)new_socket, nil
+	case .UDP: return cast(UDP_Socket)new_socket, nil
+	}
+
+	return
+}
+
+@(private)
+_dial_tcp_from_endpoint :: proc(endpoint: Endpoint, options := default_tcp_options) -> (socket: TCP_Socket, err: Network_Error) {
+	if endpoint.port == 0 {
+		return 0, .Port_Required
+	}
+
+	family := family_from_endpoint(endpoint)
+	new_socket := create_socket(family, .TCP) or_return
+	socket = new_socket.(TCP_Socket)
+
+	sockaddr := _endpoint_to_sockaddr(endpoint)
+	errno := freebsd.connect(cast(Fd)socket, &sockaddr, cast(freebsd.socklen_t)sockaddr.len)
+	if errno != nil {
+		err = cast(Dial_Error)errno
+		return
+	}
+
+	return
+}
+
+@(private)
+_bind :: proc(socket: Any_Socket, ep: Endpoint) -> (err: Network_Error) {
+	sockaddr := _endpoint_to_sockaddr(ep)
+	real_socket := any_socket_to_socket(socket)
+	errno := freebsd.bind(cast(Fd)real_socket, &sockaddr, cast(freebsd.socklen_t)sockaddr.len)
+	if errno != nil {
+		err = cast(Bind_Error)errno
+	}
+	return
+}
+
+@(private)
+_listen_tcp :: proc(interface_endpoint: Endpoint, backlog := 1000) -> (socket: TCP_Socket, err: Network_Error) {
+	family := family_from_endpoint(interface_endpoint)
+	new_socket := create_socket(family, .TCP) or_return
+	socket = new_socket.(TCP_Socket)
+
+	bind(socket, interface_endpoint) or_return
+
+	errno := freebsd.listen(cast(Fd)socket, backlog)
+	if errno != nil {
+		err = cast(Listen_Error)errno
+		return
+	}
+
+	return
+}
+
+@(private)
+_accept_tcp :: proc(sock: TCP_Socket, options := default_tcp_options) -> (client: TCP_Socket, source: Endpoint, err: Network_Error) {
+	sockaddr: freebsd.Socket_Address_Storage
+
+	result, errno := freebsd.accept(cast(Fd)sock, &sockaddr)
+	if errno != nil {
+		err = cast(Accept_Error)errno
+		return
+	}
+
+	client = cast(TCP_Socket)result
+	source = _sockaddr_to_endpoint(&sockaddr)
+	return
+}
+
+@(private)
+_close :: proc(socket: Any_Socket) {
+	real_socket := cast(Fd)any_socket_to_socket(socket)
+	// TODO: This returns an error number, but the `core:net` interface does not handle it.
+	_ = freebsd.close(real_socket)
+}
+
+@(private)
+_recv_tcp :: proc(socket: TCP_Socket, buf: []byte) -> (bytes_read: int, err: Network_Error) {
+	if len(buf) == 0 {
+		return
+	}
+	result, errno := freebsd.recv(cast(Fd)socket, buf, .NONE)
+	if errno != nil {
+		err = cast(TCP_Recv_Error)errno
+		return
+	}
+	return cast(int)result, nil
+}
+
+@(private)
+_recv_udp :: proc(socket: UDP_Socket, buf: []byte) -> (bytes_read: int, remote_endpoint: Endpoint, err: Network_Error) {
+	if len(buf) == 0 {
+		return
+	}
+	from: freebsd.Socket_Address_Storage
+
+	result, errno := freebsd.recvfrom(cast(Fd)socket, buf, .NONE, &from)
+	if errno != nil {
+		err = cast(UDP_Recv_Error)errno
+		return
+	}
+	return cast(int)result, _sockaddr_to_endpoint(&from), nil
+}
+
+@(private)
+_send_tcp :: proc(socket: TCP_Socket, buf: []byte) -> (bytes_written: int, err: Network_Error) {
+	for bytes_written < len(buf) {
+		limit := min(int(max(i32)), len(buf) - bytes_written)
+		remaining := buf[bytes_written:][:limit]
+
+		result, errno := freebsd.send(cast(Fd)socket, remaining, .NONE)
+		if errno != nil {
+			err = cast(TCP_Send_Error)errno
+			return
+		}
+		bytes_written += cast(int)result
+	}
+	return
+}
+
+@(private)
+_send_udp :: proc(socket: UDP_Socket, buf: []byte, to: Endpoint) -> (bytes_written: int, err: Network_Error) {
+	toaddr := _endpoint_to_sockaddr(to)
+	for bytes_written < len(buf) {
+		limit := min(int(max(i32)), len(buf) - bytes_written)
+		remaining := buf[bytes_written:][:limit]
+
+		result, errno := freebsd.sendto(cast(Fd)socket, remaining, .NONE, &toaddr)
+		if errno != nil {
+			err = cast(UDP_Send_Error)errno
+			return
+		}
+		bytes_written += cast(int)result
+	}
+	return
+}
+
+@(private)
+_shutdown :: proc(socket: Any_Socket, manner: Shutdown_Manner) -> (err: Network_Error) {
+	real_socket := cast(Fd)any_socket_to_socket(socket)
+	errno := freebsd.shutdown(real_socket, cast(freebsd.Shutdown_Method)manner)
+	if errno != nil {
+		return cast(Shutdown_Error)errno
+	}
+	return
+}
+
+@(private)
+_set_option :: proc(socket: Any_Socket, option: Socket_Option, value: any, loc := #caller_location) -> Network_Error {
+	// NOTE(Feoramund): I found that FreeBSD, like Linux, requires at least 32
+	// bits for a boolean socket option value. Nothing less will work.
+	bool_value: b32
+	// TODO: Assuming no larger than i32, but the system may accept i64.
+	int_value: i32
+	timeval_value: freebsd.timeval
+
+	ptr: rawptr
+	len: freebsd.socklen_t
+
+	// TODO: Verify that these options perform adequately.
+	switch option {
+	case
+		.Reuse_Address,
+		.Keep_Alive,
+		.Broadcast,
+		.Use_Loopback,
+		.Out_Of_Bounds_Data_Inline:
+		switch real in value {
+		case bool: bool_value = cast(b32)real
+		case b8:   bool_value = cast(b32)real
+		case b16:  bool_value = cast(b32)real
+		case b32:  bool_value = real
+		case b64:  bool_value = cast(b32)real
+		case:
+			panic("set_option() value must be a boolean here", loc)
+		}
+		ptr = &bool_value
+		len = size_of(bool_value)
+	case
+		.Linger,
+		.Send_Timeout,
+		.Receive_Timeout:
+			t, ok := value.(time.Duration)
+			if !ok {
+				panic("set_option() value must be a time.Duration here", loc)
+			}
+
+			micros := cast(freebsd.time_t)time.duration_microseconds(t)
+			timeval_value.usec = cast(freebsd.suseconds_t)micros % 1e6
+			timeval_value.sec = (micros - cast(freebsd.time_t)timeval_value.usec) / 1e6
+
+			ptr = &timeval_value
+			len = size_of(timeval_value)
+	case
+		.Receive_Buffer_Size,
+		.Send_Buffer_Size:
+			switch real in value {
+			case   i8: int_value = cast(i32)real
+			case   u8: int_value = cast(i32)real
+			case  i16: int_value = cast(i32)real
+			case  u16: int_value = cast(i32)real
+			case  i32: int_value = real
+			case  u32:
+				if real > u32(max(i32)) { return .Value_Out_Of_Range }
+				int_value = cast(i32)real
+			case  i64:
+				if real > i64(max(i32)) || real < i64(min(i32)) { return .Value_Out_Of_Range }
+				int_value = cast(i32)real
+			case  u64:
+				if real > u64(max(i32)) { return .Value_Out_Of_Range }
+				int_value = cast(i32)real
+			case i128:
+				if real > i128(max(i32)) || real < i128(min(i32)) { return .Value_Out_Of_Range }
+				int_value = cast(i32)real
+			case u128:
+				if real > u128(max(i32)) { return .Value_Out_Of_Range }
+				int_value = cast(i32)real
+			case  int:
+				if real > int(max(i32)) || real < int(min(i32)) { return .Value_Out_Of_Range }
+				int_value = cast(i32)real
+			case uint:
+				if real > uint(max(i32)) { return .Value_Out_Of_Range }
+				int_value = cast(i32)real
+			case:
+				panic("set_option() value must be an integer here", loc)
+			}
+	case:
+		unimplemented("set_option() option not yet implemented", loc)
+	}
+
+	real_socket := any_socket_to_socket(socket)
+	errno := freebsd.setsockopt(cast(Fd)real_socket, .SOCKET, cast(freebsd.Socket_Option)option, ptr, len)
+	if errno != nil {
+		return cast(Socket_Option_Error)errno
+	}
+
+	return nil
+}
+
+@(private)
+_set_blocking :: proc(socket: Any_Socket, should_block: bool) -> (err: Network_Error) {
+	real_socket := any_socket_to_socket(socket)
+
+	flags, errno := freebsd.fcntl_getfl(cast(freebsd.Fd)real_socket)
+	if errno != nil {
+		return cast(Set_Blocking_Error)errno
+	}
+
+	if should_block {
+		flags &= ~{ .NONBLOCK }
+	} else {
+		flags |= { .NONBLOCK }
+	}
+
+	errno = freebsd.fcntl_setfl(cast(freebsd.Fd)real_socket, flags)
+	if errno != nil {
+		return cast(Set_Blocking_Error)errno
+	}
+
+	return
+}
+
+@(private)
+_endpoint_to_sockaddr :: proc(ep: Endpoint) -> (sockaddr: freebsd.Socket_Address_Storage) {
+	switch addr in ep.address {
+	case IP4_Address:
+		(cast(^freebsd.Socket_Address_Internet)(&sockaddr))^ = {
+			len = size_of(freebsd.Socket_Address_Internet),
+			family = .INET,
+			port = cast(freebsd.in_port_t)ep.port,
+			addr = transmute(freebsd.IP4_Address)addr,
+		}
+	case IP6_Address:
+		(cast(^freebsd.Socket_Address_Internet6)(&sockaddr))^ = {
+			len = size_of(freebsd.Socket_Address_Internet),
+			family = .INET6,
+			port = cast(freebsd.in_port_t)ep.port,
+			addr = transmute(freebsd.IP6_Address)addr,
+		}
+	}
+	return
+}
+
+@(private)
+_sockaddr_to_endpoint :: proc(native_addr: ^freebsd.Socket_Address_Storage) -> (ep: Endpoint) {
+	#partial switch native_addr.family {
+	case .INET:
+		addr := cast(^freebsd.Socket_Address_Internet)native_addr
+		ep = {
+			address = transmute(IP4_Address)addr.addr.addr8,
+			port = cast(int)addr.port,
+		}
+	case .INET6:
+		addr := cast(^freebsd.Socket_Address_Internet6)native_addr
+		ep = {
+			address = transmute(IP6_Address)addr.addr.addr16,
+			port = cast(int)addr.port,
+		}
+	case:
+		panic("native_addr is neither an IP4 or IP6 address")
+	}
+	return
+}