From f072136c04e4e8f43232fa46679059018f2f77c3 Mon Sep 17 00:00:00 2001 From: Isaac Andrade Date: Mon, 2 Sep 2024 21:59:03 -0600 Subject: [PATCH] Implement POSIX linux support for poll and netinet_tcp. Incomplete support for netinet/in. --- core/sys/posix/netinet_in.odin | 168 ++++++++++++++++++++++++++++++++ core/sys/posix/netinet_tcp.odin | 2 +- core/sys/posix/poll.odin | 28 +++++- 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") }