interface_windows.odin 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. #+build windows
  2. package net
  3. /*
  4. Package net implements cross-platform Berkeley Sockets, DNS resolution and associated procedures.
  5. For other protocols and their features, see subdirectories of this package.
  6. */
  7. /*
  8. Copyright 2022 Tetralux <[email protected]>
  9. Copyright 2022 Colin Davidson <[email protected]>
  10. Copyright 2022 Jeroen van Rijn <[email protected]>.
  11. Copyright 2024 Feoramund <[email protected]>.
  12. Made available under Odin's BSD-3 license.
  13. List of contributors:
  14. Tetralux: Initial implementation
  15. Colin Davidson: Linux platform code, OSX platform code, Odin-native DNS resolver
  16. Jeroen van Rijn: Cross platform unification, code style, documentation
  17. Feoramund: FreeBSD platform code
  18. */
  19. import sys "core:sys/windows"
  20. import strings "core:strings"
  21. _enumerate_interfaces :: proc(allocator := context.allocator) -> (interfaces: []Network_Interface, err: Interfaces_Error) {
  22. context.allocator = allocator
  23. buf: []u8
  24. defer delete(buf)
  25. buf_size: u32
  26. res: u32
  27. gaa: for _ in 1..=MAX_INTERFACE_ENUMERATION_TRIES {
  28. res = sys.get_adapters_addresses(
  29. .Unspecified, // Return both IPv4 and IPv6 adapters.
  30. sys.GAA_Flags{
  31. .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.
  32. .Include_Gateways, // (Vista+) Return the addresses of default gateways.
  33. .Include_Tunnel_Binding_Order, // (Vista+) Return the adapter addresses sorted in tunnel binding order.
  34. },
  35. nil, // Reserved
  36. (^sys.IP_Adapter_Addresses)(raw_data(buf)),
  37. &buf_size,
  38. )
  39. switch res {
  40. case 111: // ERROR_BUFFER_OVERFLOW:
  41. delete(buf)
  42. buf = make([]u8, buf_size)
  43. case 0:
  44. break gaa
  45. case:
  46. set_last_platform_error(i32(res))
  47. return {}, .Unknown
  48. }
  49. }
  50. if res != 0 {
  51. return {}, .Unable_To_Enumerate_Network_Interfaces
  52. }
  53. _interfaces := make([dynamic]Network_Interface, 0, allocator)
  54. for adapter := (^sys.IP_Adapter_Addresses)(raw_data(buf)); adapter != nil; adapter = adapter.Next {
  55. friendly_name, err1 := sys.wstring_to_utf8(sys.wstring(adapter.FriendlyName), 256, allocator)
  56. if err1 != nil { return {}, .Allocation_Failure }
  57. description, err2 := sys.wstring_to_utf8(sys.wstring(adapter.Description), 256, allocator)
  58. if err2 != nil { return {}, .Allocation_Failure }
  59. dns_suffix, err3 := sys.wstring_to_utf8(sys.wstring(adapter.DnsSuffix), 256, allocator)
  60. if err3 != nil { return {}, .Allocation_Failure }
  61. interface := Network_Interface{
  62. adapter_name = strings.clone(string(adapter.AdapterName)),
  63. friendly_name = friendly_name,
  64. description = description,
  65. dns_suffix = dns_suffix,
  66. mtu = adapter.MTU,
  67. link = {
  68. transmit_speed = adapter.TransmitLinkSpeed,
  69. receive_speed = adapter.ReceiveLinkSpeed,
  70. },
  71. }
  72. if adapter.PhysicalAddressLength > 0 && adapter.PhysicalAddressLength <= len(adapter.PhysicalAddress) {
  73. interface.physical_address = physical_address_to_string(adapter.PhysicalAddress[:adapter.PhysicalAddressLength])
  74. }
  75. for u_addr := (^sys.IP_ADAPTER_UNICAST_ADDRESS_LH)(adapter.FirstUnicastAddress); u_addr != nil; u_addr = u_addr.Next {
  76. win_addr := parse_socket_address(u_addr.Address)
  77. lease := Lease{
  78. address = win_addr.address,
  79. origin = {
  80. prefix = Prefix_Origin(u_addr.PrefixOrigin),
  81. suffix = Suffix_Origin(u_addr.SuffixOrigin),
  82. },
  83. lifetime = {
  84. valid = u_addr.ValidLifetime,
  85. preferred = u_addr.PreferredLifetime,
  86. lease = u_addr.LeaseLifetime,
  87. },
  88. address_duplication = Address_Duplication(u_addr.DadState),
  89. }
  90. append(&interface.unicast, lease)
  91. }
  92. for a_addr := (^sys.IP_ADAPTER_ANYCAST_ADDRESS_XP)(adapter.FirstAnycastAddress); a_addr != nil; a_addr = a_addr.Next {
  93. addr := parse_socket_address(a_addr.Address)
  94. append(&interface.anycast, addr.address)
  95. }
  96. for m_addr := (^sys.IP_ADAPTER_MULTICAST_ADDRESS_XP)(adapter.FirstMulticastAddress); m_addr != nil; m_addr = m_addr.Next {
  97. addr := parse_socket_address(m_addr.Address)
  98. append(&interface.multicast, addr.address)
  99. }
  100. for g_addr := (^sys.IP_ADAPTER_GATEWAY_ADDRESS_LH)(adapter.FirstGatewayAddress); g_addr != nil; g_addr = g_addr.Next {
  101. addr := parse_socket_address(g_addr.Address)
  102. append(&interface.gateways, addr.address)
  103. }
  104. interface.dhcp_v4 = parse_socket_address(adapter.Dhcpv4Server).address
  105. interface.dhcp_v6 = parse_socket_address(adapter.Dhcpv6Server).address
  106. switch adapter.OperStatus {
  107. case .Up: interface.link.state = {.Up}
  108. case .Down: interface.link.state = {.Down}
  109. case .Testing: interface.link.state = {.Testing}
  110. case .Dormant: interface.link.state = {.Dormant}
  111. case .NotPresent: interface.link.state = {.Not_Present}
  112. case .LowerLayerDown: interface.link.state = {.Lower_Layer_Down}
  113. case .Unknown: fallthrough
  114. case: interface.link.state = {}
  115. }
  116. interface.tunnel_type = Tunnel_Type(adapter.TunnelType)
  117. append(&_interfaces, interface)
  118. }
  119. return _interfaces[:], {}
  120. }
  121. /*
  122. Interpret SOCKET_ADDRESS as an Address
  123. */
  124. parse_socket_address :: proc(addr_in: sys.SOCKET_ADDRESS) -> (addr: Endpoint) {
  125. if addr_in.lpSockaddr == nil {
  126. return // Empty or invalid address type
  127. }
  128. sock := addr_in.lpSockaddr^
  129. switch sock.sa_family {
  130. case u16(sys.AF_INET):
  131. win_addr := cast(^sys.sockaddr_in)addr_in.lpSockaddr
  132. port := int(win_addr.sin_port)
  133. return Endpoint {
  134. address = IP4_Address(transmute([4]byte)win_addr.sin_addr),
  135. port = port,
  136. }
  137. case u16(sys.AF_INET6):
  138. win_addr := cast(^sys.sockaddr_in6)addr_in.lpSockaddr
  139. port := int(win_addr.sin6_port)
  140. return Endpoint {
  141. address = IP6_Address(transmute([8]u16be)win_addr.sin6_addr),
  142. port = port,
  143. }
  144. case: return // Empty or invalid address type
  145. }
  146. unreachable()
  147. }