mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-21 05:45:19 +00:00
Implement new sys/unix package
This commit is contained in:
@@ -21,120 +21,124 @@ package net
|
||||
TODO: When we have raw sockets, split off into its own file for Linux so we can use the NETLINK protocol and bypass libc.
|
||||
*/
|
||||
|
||||
import "core:os"
|
||||
import "core:strings"
|
||||
//import "core:strings"
|
||||
|
||||
|
||||
// TODO(flysand): regression
|
||||
// NOTE(flysand): https://man7.org/linux/man-pages/man7/netlink.7.html
|
||||
// apparently musl libc uses this to enumerate network interfaces
|
||||
@(private)
|
||||
_enumerate_interfaces :: proc(allocator := context.allocator) -> (interfaces: []Network_Interface, err: Network_Error) {
|
||||
context.allocator = allocator
|
||||
|
||||
head: ^os.ifaddrs
|
||||
// head: ^os.ifaddrs
|
||||
|
||||
if res := os._getifaddrs(&head); res < 0 {
|
||||
return {}, .Unable_To_Enumerate_Network_Interfaces
|
||||
}
|
||||
// if res := os._getifaddrs(&head); res < 0 {
|
||||
// return {}, .Unable_To_Enumerate_Network_Interfaces
|
||||
// }
|
||||
|
||||
/*
|
||||
Unlike Windows, *nix regrettably doesn't return all it knows about an interface in one big struct.
|
||||
We're going to have to iterate over a list and coalesce information as we go.
|
||||
*/
|
||||
ifaces: map[string]^Network_Interface
|
||||
defer delete(ifaces)
|
||||
// /*
|
||||
// Unlike Windows, *nix regrettably doesn't return all it knows about an interface in one big struct.
|
||||
// We're going to have to iterate over a list and coalesce information as we go.
|
||||
// */
|
||||
// ifaces: map[string]^Network_Interface
|
||||
// defer delete(ifaces)
|
||||
|
||||
for ifaddr := head; ifaddr != nil; ifaddr = ifaddr.next {
|
||||
adapter_name := string(ifaddr.name)
|
||||
// for ifaddr := head; ifaddr != nil; ifaddr = ifaddr.next {
|
||||
// adapter_name := string(ifaddr.name)
|
||||
|
||||
/*
|
||||
Check if we have seen this interface name before so we can reuse the `Network_Interface`.
|
||||
Else, create a new one.
|
||||
*/
|
||||
if adapter_name not_in ifaces {
|
||||
ifaces[adapter_name] = new(Network_Interface)
|
||||
ifaces[adapter_name].adapter_name = strings.clone(adapter_name)
|
||||
}
|
||||
iface := ifaces[adapter_name]
|
||||
// /*
|
||||
// Check if we have seen this interface name before so we can reuse the `Network_Interface`.
|
||||
// Else, create a new one.
|
||||
// */
|
||||
// if adapter_name not_in ifaces {
|
||||
// ifaces[adapter_name] = new(Network_Interface)
|
||||
// ifaces[adapter_name].adapter_name = strings.clone(adapter_name)
|
||||
// }
|
||||
// iface := ifaces[adapter_name]
|
||||
|
||||
address: Address
|
||||
netmask: Netmask
|
||||
// address: Address
|
||||
// netmask: Netmask
|
||||
|
||||
if ifaddr.address != nil {
|
||||
switch int(ifaddr.address.sa_family) {
|
||||
case os.AF_INET, os.AF_INET6:
|
||||
address = _sockaddr_basic_to_endpoint(ifaddr.address).address
|
||||
// if ifaddr.address != nil {
|
||||
// switch int(ifaddr.address.sa_family) {
|
||||
// case os.AF_INET, os.AF_INET6:
|
||||
// address = _sockaddr_basic_to_endpoint(ifaddr.address).address
|
||||
|
||||
case os.AF_PACKET:
|
||||
/*
|
||||
For some obscure reason the 64-bit `getifaddrs` call returns a pointer to a
|
||||
32-bit `RTNL_LINK_STATS` structure, which of course means that tx/rx byte count
|
||||
is truncated beyond usefulness.
|
||||
// case os.AF_PACKET:
|
||||
// /*
|
||||
// For some obscure reason the 64-bit `getifaddrs` call returns a pointer to a
|
||||
// 32-bit `RTNL_LINK_STATS` structure, which of course means that tx/rx byte count
|
||||
// is truncated beyond usefulness.
|
||||
|
||||
We're not going to retrieve stats now. Instead this serves as a reminder to use
|
||||
the NETLINK protocol for this purpose.
|
||||
// We're not going to retrieve stats now. Instead this serves as a reminder to use
|
||||
// the NETLINK protocol for this purpose.
|
||||
|
||||
But in case you were curious:
|
||||
stats := transmute(^os.rtnl_link_stats)ifaddr.data
|
||||
fmt.println(stats)
|
||||
*/
|
||||
case:
|
||||
}
|
||||
}
|
||||
// But in case you were curious:
|
||||
// stats := transmute(^os.rtnl_link_stats)ifaddr.data
|
||||
// fmt.println(stats)
|
||||
// */
|
||||
// case:
|
||||
// }
|
||||
// }
|
||||
|
||||
if ifaddr.netmask != nil {
|
||||
switch int(ifaddr.netmask.sa_family) {
|
||||
case os.AF_INET, os.AF_INET6:
|
||||
netmask = Netmask(_sockaddr_basic_to_endpoint(ifaddr.netmask).address)
|
||||
case:
|
||||
}
|
||||
}
|
||||
// if ifaddr.netmask != nil {
|
||||
// switch int(ifaddr.netmask.sa_family) {
|
||||
// case os.AF_INET, os.AF_INET6:
|
||||
// netmask = Netmask(_sockaddr_basic_to_endpoint(ifaddr.netmask).address)
|
||||
// case:
|
||||
// }
|
||||
// }
|
||||
|
||||
if ifaddr.broadcast_or_dest != nil && .BROADCAST in ifaddr.flags {
|
||||
switch int(ifaddr.broadcast_or_dest.sa_family) {
|
||||
case os.AF_INET, os.AF_INET6:
|
||||
broadcast := _sockaddr_basic_to_endpoint(ifaddr.broadcast_or_dest).address
|
||||
append(&iface.multicast, broadcast)
|
||||
case:
|
||||
}
|
||||
}
|
||||
// if ifaddr.broadcast_or_dest != nil && .BROADCAST in ifaddr.flags {
|
||||
// switch int(ifaddr.broadcast_or_dest.sa_family) {
|
||||
// case os.AF_INET, os.AF_INET6:
|
||||
// broadcast := _sockaddr_basic_to_endpoint(ifaddr.broadcast_or_dest).address
|
||||
// append(&iface.multicast, broadcast)
|
||||
// case:
|
||||
// }
|
||||
// }
|
||||
|
||||
if address != nil {
|
||||
lease := Lease{
|
||||
address = address,
|
||||
netmask = netmask,
|
||||
}
|
||||
append(&iface.unicast, lease)
|
||||
}
|
||||
// if address != nil {
|
||||
// lease := Lease{
|
||||
// address = address,
|
||||
// netmask = netmask,
|
||||
// }
|
||||
// append(&iface.unicast, lease)
|
||||
// }
|
||||
|
||||
/*
|
||||
TODO: Refine this based on the type of adapter.
|
||||
*/
|
||||
state := Link_State{}
|
||||
// /*
|
||||
// TODO: Refine this based on the type of adapter.
|
||||
// */
|
||||
// state := Link_State{}
|
||||
|
||||
if .UP in ifaddr.flags {
|
||||
state |= {.Up}
|
||||
}
|
||||
// if .UP in ifaddr.flags {
|
||||
// state |= {.Up}
|
||||
// }
|
||||
|
||||
if .DORMANT in ifaddr.flags {
|
||||
state |= {.Dormant}
|
||||
}
|
||||
// if .DORMANT in ifaddr.flags {
|
||||
// state |= {.Dormant}
|
||||
// }
|
||||
|
||||
if .LOOPBACK in ifaddr.flags {
|
||||
state |= {.Loopback}
|
||||
}
|
||||
iface.link.state = state
|
||||
}
|
||||
// if .LOOPBACK in ifaddr.flags {
|
||||
// state |= {.Loopback}
|
||||
// }
|
||||
// iface.link.state = state
|
||||
// }
|
||||
|
||||
/*
|
||||
Free the OS structures.
|
||||
*/
|
||||
os._freeifaddrs(head)
|
||||
// /*
|
||||
// Free the OS structures.
|
||||
// */
|
||||
// os._freeifaddrs(head)
|
||||
|
||||
/*
|
||||
Turn the map into a slice to return.
|
||||
*/
|
||||
_interfaces := make([dynamic]Network_Interface, 0, allocator)
|
||||
for _, iface in ifaces {
|
||||
append(&_interfaces, iface^)
|
||||
free(iface)
|
||||
}
|
||||
return _interfaces[:], {}
|
||||
// /*
|
||||
// Turn the map into a slice to return.
|
||||
// */
|
||||
// _interfaces := make([dynamic]Network_Interface, 0, allocator)
|
||||
// for _, iface in ifaces {
|
||||
// append(&_interfaces, iface^)
|
||||
// free(iface)
|
||||
// }
|
||||
// return _interfaces[:], {}
|
||||
return nil, {}
|
||||
}
|
||||
Reference in New Issue
Block a user