interface_windows.odin 5.7 KB

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