interface_windows.odin 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  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. 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: Network_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. return {}, Platform_Error(res)
  47. }
  48. }
  49. if res != 0 {
  50. return {}, .Unable_To_Enumerate_Network_Interfaces
  51. }
  52. _interfaces := make([dynamic]Network_Interface, 0, allocator)
  53. for adapter := (^sys.IP_Adapter_Addresses)(raw_data(buf)); adapter != nil; adapter = adapter.Next {
  54. friendly_name, err1 := sys.wstring_to_utf8(sys.wstring(adapter.FriendlyName), 256, allocator)
  55. if err1 != nil { return {}, Platform_Error(err1) }
  56. description, err2 := sys.wstring_to_utf8(sys.wstring(adapter.Description), 256, allocator)
  57. if err2 != nil { return {}, Platform_Error(err2) }
  58. dns_suffix, err3 := sys.wstring_to_utf8(sys.wstring(adapter.DnsSuffix), 256, allocator)
  59. if err3 != nil { return {}, Platform_Error(err3) }
  60. interface := Network_Interface{
  61. adapter_name = strings.clone(string(adapter.AdapterName)),
  62. friendly_name = friendly_name,
  63. description = description,
  64. dns_suffix = dns_suffix,
  65. mtu = adapter.MTU,
  66. link = {
  67. transmit_speed = adapter.TransmitLinkSpeed,
  68. receive_speed = adapter.ReceiveLinkSpeed,
  69. },
  70. }
  71. if adapter.PhysicalAddressLength > 0 && adapter.PhysicalAddressLength <= len(adapter.PhysicalAddress) {
  72. interface.physical_address = physical_address_to_string(adapter.PhysicalAddress[:adapter.PhysicalAddressLength])
  73. }
  74. for u_addr := (^sys.IP_ADAPTER_UNICAST_ADDRESS_LH)(adapter.FirstUnicastAddress); u_addr != nil; u_addr = u_addr.Next {
  75. win_addr := parse_socket_address(u_addr.Address)
  76. lease := Lease{
  77. address = win_addr.address,
  78. origin = {
  79. prefix = Prefix_Origin(u_addr.PrefixOrigin),
  80. suffix = Suffix_Origin(u_addr.SuffixOrigin),
  81. },
  82. lifetime = {
  83. valid = u_addr.ValidLifetime,
  84. preferred = u_addr.PreferredLifetime,
  85. lease = u_addr.LeaseLifetime,
  86. },
  87. address_duplication = Address_Duplication(u_addr.DadState),
  88. }
  89. append(&interface.unicast, lease)
  90. }
  91. for a_addr := (^sys.IP_ADAPTER_ANYCAST_ADDRESS_XP)(adapter.FirstAnycastAddress); a_addr != nil; a_addr = a_addr.Next {
  92. addr := parse_socket_address(a_addr.Address)
  93. append(&interface.anycast, addr.address)
  94. }
  95. for m_addr := (^sys.IP_ADAPTER_MULTICAST_ADDRESS_XP)(adapter.FirstMulticastAddress); m_addr != nil; m_addr = m_addr.Next {
  96. addr := parse_socket_address(m_addr.Address)
  97. append(&interface.multicast, addr.address)
  98. }
  99. for g_addr := (^sys.IP_ADAPTER_GATEWAY_ADDRESS_LH)(adapter.FirstGatewayAddress); g_addr != nil; g_addr = g_addr.Next {
  100. addr := parse_socket_address(g_addr.Address)
  101. append(&interface.gateways, addr.address)
  102. }
  103. interface.dhcp_v4 = parse_socket_address(adapter.Dhcpv4Server).address
  104. interface.dhcp_v6 = parse_socket_address(adapter.Dhcpv6Server).address
  105. switch adapter.OperStatus {
  106. case .Up: interface.link.state = {.Up}
  107. case .Down: interface.link.state = {.Down}
  108. case .Testing: interface.link.state = {.Testing}
  109. case .Dormant: interface.link.state = {.Dormant}
  110. case .NotPresent: interface.link.state = {.Not_Present}
  111. case .LowerLayerDown: interface.link.state = {.Lower_Layer_Down}
  112. case .Unknown: fallthrough
  113. case: interface.link.state = {}
  114. }
  115. interface.tunnel_type = Tunnel_Type(adapter.TunnelType)
  116. append(&_interfaces, interface)
  117. }
  118. return _interfaces[:], {}
  119. }
  120. /*
  121. Interpret SOCKET_ADDRESS as an Address
  122. */
  123. parse_socket_address :: proc(addr_in: sys.SOCKET_ADDRESS) -> (addr: Endpoint) {
  124. if addr_in.lpSockaddr == nil {
  125. return // Empty or invalid address type
  126. }
  127. sock := addr_in.lpSockaddr^
  128. switch sock.sa_family {
  129. case u16(sys.AF_INET):
  130. win_addr := cast(^sys.sockaddr_in)addr_in.lpSockaddr
  131. port := int(win_addr.sin_port)
  132. return Endpoint {
  133. address = IP4_Address(transmute([4]byte)win_addr.sin_addr),
  134. port = port,
  135. }
  136. case u16(sys.AF_INET6):
  137. win_addr := cast(^sys.sockaddr_in6)addr_in.lpSockaddr
  138. port := int(win_addr.sin6_port)
  139. return Endpoint {
  140. address = IP6_Address(transmute([8]u16be)win_addr.sin6_addr),
  141. port = port,
  142. }
  143. case: return // Empty or invalid address type
  144. }
  145. unreachable()
  146. }