123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- package net
- //+build windows
- /*
- Package net implements cross-platform Berkeley Sockets, DNS resolution and associated procedures.
- For other protocols and their features, see subdirectories of this package.
- */
- /*
- Copyright 2022 Tetralux <[email protected]>
- Copyright 2022 Colin Davidson <[email protected]>
- Copyright 2022 Jeroen van Rijn <[email protected]>.
- Made available under Odin's BSD-3 license.
- List of contributors:
- Tetralux: Initial implementation
- Colin Davidson: Linux platform code, OSX platform code, Odin-native DNS resolver
- Jeroen van Rijn: Cross platform unification, code style, documentation
- */
- import sys "core:sys/windows"
- import strings "core:strings"
- _enumerate_interfaces :: proc(allocator := context.allocator) -> (interfaces: []Network_Interface, err: Network_Error) {
- context.allocator = allocator
- buf: []u8
- defer delete(buf)
- buf_size: u32
- res: u32
- gaa: for _ in 1..=MAX_INTERFACE_ENUMERATION_TRIES {
- res = sys.get_adapters_addresses(
- .Unspecified, // Return both IPv4 and IPv6 adapters.
- sys.GAA_Flags{
- .Include_Prefix, // (XP SP1+) Return a list of IP address prefixes on this adapter. When this flag is set, IP address prefixes are returned for both IPv6 and IPv4 addresses.
- .Include_Gateways, // (Vista+) Return the addresses of default gateways.
- .Include_Tunnel_Binding_Order, // (Vista+) Return the adapter addresses sorted in tunnel binding order.
- },
- nil, // Reserved
- (^sys.IP_Adapter_Addresses)(raw_data(buf)),
- &buf_size,
- )
- switch res {
- case 111: // ERROR_BUFFER_OVERFLOW:
- delete(buf)
- buf = make([]u8, buf_size)
- case 0:
- break gaa
- case:
- return {}, Platform_Error(res)
- }
- }
- if res != 0 {
- return {}, .Unable_To_Enumerate_Network_Interfaces
- }
- _interfaces := make([dynamic]Network_Interface, 0, allocator)
- for adapter := (^sys.IP_Adapter_Addresses)(raw_data(buf)); adapter != nil; adapter = adapter.Next {
- friendly_name, err1 := sys.wstring_to_utf8(sys.wstring(adapter.FriendlyName), 256, allocator)
- if err1 != nil { return {}, Platform_Error(err1) }
- description, err2 := sys.wstring_to_utf8(sys.wstring(adapter.Description), 256, allocator)
- if err2 != nil { return {}, Platform_Error(err2) }
- dns_suffix, err3 := sys.wstring_to_utf8(sys.wstring(adapter.DnsSuffix), 256, allocator)
- if err3 != nil { return {}, Platform_Error(err3) }
- interface := Network_Interface{
- adapter_name = strings.clone(string(adapter.AdapterName)),
- friendly_name = friendly_name,
- description = description,
- dns_suffix = dns_suffix,
- mtu = adapter.MTU,
- link = {
- transmit_speed = adapter.TransmitLinkSpeed,
- receive_speed = adapter.ReceiveLinkSpeed,
- },
- }
- if adapter.PhysicalAddressLength > 0 && adapter.PhysicalAddressLength <= len(adapter.PhysicalAddress) {
- interface.physical_address = physical_address_to_string(adapter.PhysicalAddress[:adapter.PhysicalAddressLength])
- }
- for u_addr := (^sys.IP_ADAPTER_UNICAST_ADDRESS_LH)(adapter.FirstUnicastAddress); u_addr != nil; u_addr = u_addr.Next {
- win_addr := parse_socket_address(u_addr.Address)
- lease := Lease{
- address = win_addr.address,
- origin = {
- prefix = Prefix_Origin(u_addr.PrefixOrigin),
- suffix = Suffix_Origin(u_addr.SuffixOrigin),
- },
- lifetime = {
- valid = u_addr.ValidLifetime,
- preferred = u_addr.PreferredLifetime,
- lease = u_addr.LeaseLifetime,
- },
- address_duplication = Address_Duplication(u_addr.DadState),
- }
- append(&interface.unicast, lease)
- }
- for a_addr := (^sys.IP_ADAPTER_ANYCAST_ADDRESS_XP)(adapter.FirstAnycastAddress); a_addr != nil; a_addr = a_addr.Next {
- addr := parse_socket_address(a_addr.Address)
- append(&interface.anycast, addr.address)
- }
- for m_addr := (^sys.IP_ADAPTER_MULTICAST_ADDRESS_XP)(adapter.FirstMulticastAddress); m_addr != nil; m_addr = m_addr.Next {
- addr := parse_socket_address(m_addr.Address)
- append(&interface.multicast, addr.address)
- }
- for g_addr := (^sys.IP_ADAPTER_GATEWAY_ADDRESS_LH)(adapter.FirstGatewayAddress); g_addr != nil; g_addr = g_addr.Next {
- addr := parse_socket_address(g_addr.Address)
- append(&interface.gateways, addr.address)
- }
- interface.dhcp_v4 = parse_socket_address(adapter.Dhcpv4Server).address
- interface.dhcp_v6 = parse_socket_address(adapter.Dhcpv6Server).address
- switch adapter.OperStatus {
- case .Up: interface.link.state = {.Up}
- case .Down: interface.link.state = {.Down}
- case .Testing: interface.link.state = {.Testing}
- case .Dormant: interface.link.state = {.Dormant}
- case .NotPresent: interface.link.state = {.Not_Present}
- case .LowerLayerDown: interface.link.state = {.Lower_Layer_Down}
- case .Unknown: fallthrough
- case: interface.link.state = {}
- }
- interface.tunnel_type = Tunnel_Type(adapter.TunnelType)
- append(&_interfaces, interface)
- }
- return _interfaces[:], {}
- }
- /*
- Interpret SOCKET_ADDRESS as an Address
- */
- parse_socket_address :: proc(addr_in: sys.SOCKET_ADDRESS) -> (addr: Endpoint) {
- if addr_in.lpSockaddr == nil {
- return // Empty or invalid address type
- }
- sock := addr_in.lpSockaddr^
- switch sock.sa_family {
- case u16(sys.AF_INET):
- win_addr := cast(^sys.sockaddr_in)addr_in.lpSockaddr
- port := int(win_addr.sin_port)
- return Endpoint {
- address = IP4_Address(transmute([4]byte)win_addr.sin_addr),
- port = port,
- }
- case u16(sys.AF_INET6):
- win_addr := cast(^sys.sockaddr_in6)addr_in.lpSockaddr
- port := int(win_addr.sin6_port)
- return Endpoint {
- address = IP6_Address(transmute([8]u16be)win_addr.sin6_addr),
- port = port,
- }
- case: return // Empty or invalid address type
- }
- unreachable()
- }
|