aboutsummaryrefslogtreecommitdiff
path: root/core/sys
diff options
context:
space:
mode:
authorIsaac Andrade <andradei@proton.me>2024-09-02 21:59:03 -0600
committerIsaac Andrade <andradei@proton.me>2024-09-02 21:59:03 -0600
commitf072136c04e4e8f43232fa46679059018f2f77c3 (patch)
treefda15c6b9919dca42ef6281779f9cc6929b12d18 /core/sys
parent35f961d80f11fca6c0d1f8c6cb7d8d149f3e71f2 (diff)
Implement POSIX linux support for poll and netinet_tcp. Incomplete support for netinet/in.
Diffstat (limited to 'core/sys')
-rw-r--r--core/sys/posix/netinet_in.odin168
-rw-r--r--core/sys/posix/netinet_tcp.odin2
-rw-r--r--core/sys/posix/poll.odin28
3 files changed, 196 insertions, 2 deletions
diff --git a/core/sys/posix/netinet_in.odin b/core/sys/posix/netinet_in.odin
index 3926c5288..70427e8af 100644
--- a/core/sys/posix/netinet_in.odin
+++ b/core/sys/posix/netinet_in.odin
@@ -194,6 +194,174 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
)
}
+} else when ODIN_OS == .Linux {
+
+ in_addr :: struct {
+ s_addr: in_addr_t, /* [PSX] big endian address */
+ }
+
+ in6_addr :: struct {
+ using _: struct #raw_union {
+ s6_addr: [16]c.uint8_t, /* [PSX] big endian address */
+ __u6_addr16: [8]c.uint16_t,
+ __u6_addr32: [4]c.uint32_t,
+ },
+ }
+
+ sockaddr_in :: struct {
+ sin_family: sa_family_t, /* [PSX] AF_INET (but a smaller size) */
+ sin_port: in_port_t, /* [PSX] port number */
+ sin_addr: in_addr, /* [PSX] IP address */
+ sin_zero: [size_of(sockaddr) -
+ u16 -
+ size_of(in_port_t) -
+ size_of(in_addr)]c.char,
+ }
+
+ sockaddr_in6 :: struct {
+ sin6_family: sa_family_t, /* [PSX] AF_INET6 (but a smaller size) */
+ sin6_port: in_port_t, /* [PSX] port number */
+ sin6_flowinfo: u32be, /* [PSX] IPv6 traffic class and flow information */
+ sin6_addr: in6_addr, /* [PSX] IPv6 address */
+ sin6_scope_id: c.uint32_t, /* [PSX] set of interfaces for a scope */
+ }
+
+ ipv6_mreq :: struct {
+ ipv6mr_multiaddr: in6_addr, /* [PSX] IPv6 multicast address */
+ ipv6mr_interface: c.int, /* [PSX] interface index */
+ }
+
+ IPPROTO_IP :: 0
+ IPPROTO_ICMP :: 1
+ IPPROTO_IPV6 :: 41
+ IPPROTO_RAW :: 255
+ IPPROTO_TCP :: 6
+ IPPROTO_UDP :: 17
+
+ INADDR_ANY :: 0x00000000
+ INADDR_BROADCAST :: 0xFFFFFFFF
+
+ IPV6_MULTICAST_IF :: 17
+ IPV6_UNICAST_HOPS :: 16
+ IPV6_MULTICAST_HOPS :: 18
+ IPV6_MULTICAST_LOOP :: 19
+ IPV6_JOIN_GROUP :: 20
+ IPV6_LEAVE_GROUP :: 21
+ IPV6_V6ONLY :: 26
+
+ // TODO: (Isaac Andrade, 2024-09-02) Copied from the BSDs block above. Needs to be implemented for Linux.
+ // Get mentoring from a more senior C and Odin developer or leave this to one of them.
+
+ //IN6_IS_ADDR_UNSPECIFIED :: #force_inline proc "contextless" (a: in6_addr) -> b32 {
+ // return a.s6_addr == 0
+ //}
+ //
+ //IN6_IS_ADDR_LOOPBACK :: #force_inline proc "contextless" (a: in6_addr) -> b32 {
+ // a := a
+ // return (
+ // (^c.uint32_t)(&a.s6_addr[0])^ == 0 &&
+ // (^c.uint32_t)(&a.s6_addr[4])^ == 0 &&
+ // (^c.uint32_t)(&a.s6_addr[8])^ == 0 &&
+ // (^u32be)(&a.s6_addr[12])^ == 1 \
+ // )
+ //}
+ //
+ //IN6_IS_ADDR_MULTICAST :: #force_inline proc "contextless" (a: in6_addr) -> b32 {
+ // return a.s6_addr[0] == 0xff
+ //}
+ //
+ //IN6_IS_ADDR_LINKLOCAL :: #force_inline proc "contextless" (a: in6_addr) -> b32 {
+ // return a.s6_addr[0] == 0xfe && a.s6_addr[1] & 0xc0 == 0x80
+ //}
+ //
+ //IN6_IS_ADDR_SITELOCAL :: #force_inline proc "contextless" (a: in6_addr) -> b32 {
+ // return a.s6_addr[0] == 0xfe && a.s6_addr[1] & 0xc0 == 0xc0
+ //}
+ //
+ //IN6_IS_ADDR_V4MAPPED :: #force_inline proc "contextless" (a: in6_addr) -> b32 {
+ // a := a
+ // return (
+ // (^c.uint32_t)(&a.s6_addr[0])^ == 0 &&
+ // (^c.uint32_t)(&a.s6_addr[4])^ == 0 &&
+ // (^u32be)(&a.s6_addr[8])^ == 0x0000ffff \
+ // )
+ //}
+ //
+ //IN6_IS_ADDR_V4COMPAT :: #force_inline proc "contextless" (a: in6_addr) -> b32 {
+ // a := a
+ // return (
+ // (^c.uint32_t)(&a.s6_addr[0])^ == 0 &&
+ // (^c.uint32_t)(&a.s6_addr[4])^ == 0 &&
+ // (^c.uint32_t)(&a.s6_addr[8])^ == 0 &&
+ // (^c.uint32_t)(&a.s6_addr[12])^ != 0 &&
+ // (^u32be)(&a.s6_addr[12])^ != 1 \
+ // )
+ //}
+ //
+ //@(private)
+ //__IPV6_ADDR_SCOPE_NODELOCAL :: 0x01
+ //@(private)
+ //__IPV6_ADDR_SCOPE_LINKLOCAL :: 0x02
+ //@(private)
+ //__IPV6_ADDR_SCOPE_SITELOCAL :: 0x05
+ //@(private)
+ //__IPV6_ADDR_SCOPE_ORGLOCAL :: 0x08
+ //@(private)
+ //__IPV6_ADDR_SCOPE_GLOBAL :: 0x0e
+ //
+ //@(private)
+ //IPV6_ADDR_MC_FLAGS :: #force_inline proc "contextless" (a: in6_addr) -> c.uint8_t {
+ // return a.s6_addr[1] & 0xf0
+ //}
+ //
+ //@(private)
+ //IPV6_ADDR_MC_FLAGS_TRANSIENT :: 0x10
+ //@(private)
+ //IPV6_ADDR_MC_FLAGS_PREFIX :: 0x20
+ //@(private)
+ //IPV6_ADDR_MC_FLAGS_UNICAST_BASED :: IPV6_ADDR_MC_FLAGS_TRANSIENT | IPV6_ADDR_MC_FLAGS_PREFIX
+ //
+ //@(private)
+ //__IPV6_ADDR_MC_SCOPE :: #force_inline proc "contextless" (a: in6_addr) -> c.uint8_t {
+ // return a.s6_addr[1] & 0x0f
+ //}
+ //
+ //IN6_IS_ADDR_MC_NODELOCAL :: #force_inline proc "contextless" (a: in6_addr) -> b32 {
+ // return (
+ // IN6_IS_ADDR_MULTICAST(a) &&
+ // (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_NODELOCAL) \
+ // )
+ //}
+ //
+ //IN6_IS_ADDR_MC_LINKLOCAL :: #force_inline proc "contextless" (a: in6_addr) -> b32 {
+ // return (
+ // IN6_IS_ADDR_MULTICAST(a) &&
+ // (IPV6_ADDR_MC_FLAGS(a) != IPV6_ADDR_MC_FLAGS_UNICAST_BASED) &&
+ // (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_LINKLOCAL) \
+ // )
+ //}
+ //
+ //IN6_IS_ADDR_MC_SITELOCAL :: #force_inline proc "contextless" (a: in6_addr) -> b32 {
+ // return (
+ // IN6_IS_ADDR_MULTICAST(a) &&
+ // (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_SITELOCAL) \
+ // )
+ //}
+ //
+ //IN6_IS_ADDR_MC_ORGLOCAL :: #force_inline proc "contextless" (a: in6_addr) -> b32 {
+ // return (
+ // IN6_IS_ADDR_MULTICAST(a) &&
+ // (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_ORGLOCAL) \
+ // )
+ //}
+ //
+ //IN6_IS_ADDR_MC_GLOBAL :: #force_inline proc "contextless" (a: in6_addr) -> b32 {
+ // return (
+ // IN6_IS_ADDR_MULTICAST(a) &&
+ // (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_GLOBAL) \
+ // )
+ //}
+
} else {
#panic("posix is unimplemented for the current target")
}
diff --git a/core/sys/posix/netinet_tcp.odin b/core/sys/posix/netinet_tcp.odin
index ecd084b38..284351732 100644
--- a/core/sys/posix/netinet_tcp.odin
+++ b/core/sys/posix/netinet_tcp.odin
@@ -2,7 +2,7 @@ package posix
// netinet/tcp.h - definitions for the Internet Transmission Control Protocol (TCP)
-when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD {
+when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux {
TCP_NODELAY :: 0x01
diff --git a/core/sys/posix/poll.odin b/core/sys/posix/poll.odin
index 3e825e009..7f23de267 100644
--- a/core/sys/posix/poll.odin
+++ b/core/sys/posix/poll.odin
@@ -21,11 +21,17 @@ foreign lib {
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html ]]
*/
- poll :: proc(fds: [^]pollfd, nfds: nfds_t, timeout: c.int) -> c.int ---
+ poll :: proc(fds: [^]pollfd, nfds: nfds_t, timeout: c.int) -> Poll_Error ---
}
nfds_t :: c.uint
+Poll_Error :: enum c.int {
+ EAGAIN = Errno.EAGAIN,
+ EINTR = Errno.EINTR,
+ EINVAL = Errno.EINVAL,
+}
+
Poll_Event_Bits :: enum c.short {
// Data other than high-priority data may be read without blocking.
IN = log2(POLLIN),
@@ -72,6 +78,26 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
POLLHUP :: 0x0010
POLLNVAL :: 0x0020
+} else when ODIN_OS == .Linux {
+
+ pollfd :: struct {
+ fd: FD, /* [PSX] the following descriptor being polled */
+ events: Poll_Event, /* [PSX] the input event flags */
+ revents: Poll_Event, /* [PSX] the output event flags */
+ }
+
+ POLLIN :: 0x0001
+ POLLRDNORM :: 0x0040
+ POLLRDBAND :: 0x0080
+ POLLPRI :: 0x0002
+ POLLOUT :: 0x0004
+ POLLWRNORM :: 0x0100
+ POLLWRBAND :: 0x0200
+
+ POLLERR :: 0x0008
+ POLLHUP :: 0x0010
+ POLLNVAL :: 0x0020
+
} else {
#panic("posix is unimplemented for the current target")
}