interface_darwin.odin 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. package net
  2. //+build darwin
  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 "core:os"
  18. import "core:strings"
  19. @(private)
  20. _enumerate_interfaces :: proc(allocator := context.allocator) -> (interfaces: []Network_Interface, err: Network_Error) {
  21. context.allocator = allocator
  22. head: ^os.ifaddrs
  23. if res := os._getifaddrs(&head); res < 0 {
  24. return {}, .Unable_To_Enumerate_Network_Interfaces
  25. }
  26. /*
  27. Unlike Windows, *nix regrettably doesn't return all it knows about an interface in one big struct.
  28. We're going to have to iterate over a list and coalesce information as we go.
  29. */
  30. ifaces: map[string]^Network_Interface
  31. defer delete(ifaces)
  32. for ifaddr := head; ifaddr != nil; ifaddr = ifaddr.next {
  33. adapter_name := string(ifaddr.name)
  34. /*
  35. Check if we have seen this interface name before so we can reuse the `Network_Interface`.
  36. Else, create a new one.
  37. */
  38. if adapter_name not_in ifaces {
  39. ifaces[adapter_name] = new(Network_Interface)
  40. ifaces[adapter_name].adapter_name = strings.clone(adapter_name)
  41. }
  42. iface := ifaces[adapter_name]
  43. address: Address
  44. netmask: Netmask
  45. if ifaddr.address != nil {
  46. switch int(ifaddr.address.family) {
  47. case os.AF_INET, os.AF_INET6:
  48. address = _sockaddr_basic_to_endpoint(ifaddr.address).address
  49. case:
  50. }
  51. }
  52. if ifaddr.netmask != nil {
  53. switch int(ifaddr.netmask.family) {
  54. case os.AF_INET, os.AF_INET6:
  55. netmask = Netmask(_sockaddr_basic_to_endpoint(ifaddr.netmask).address)
  56. case:
  57. }
  58. }
  59. if ifaddr.broadcast_or_dest != nil && .BROADCAST in ifaddr.flags {
  60. switch int(ifaddr.broadcast_or_dest.family) {
  61. case os.AF_INET, os.AF_INET6:
  62. broadcast := _sockaddr_basic_to_endpoint(ifaddr.broadcast_or_dest).address
  63. append(&iface.multicast, broadcast)
  64. case:
  65. }
  66. }
  67. if address != nil {
  68. lease := Lease{
  69. address = address,
  70. netmask = netmask,
  71. }
  72. append(&iface.unicast, lease)
  73. }
  74. /*
  75. TODO: Refine this based on the type of adapter.
  76. */
  77. state := Link_State{}
  78. if .UP in ifaddr.flags {
  79. state |= {.Up}
  80. }
  81. /*if .DORMANT in ifaddr.flags {
  82. state |= {.Dormant}
  83. }*/
  84. if .LOOPBACK in ifaddr.flags {
  85. state |= {.Loopback}
  86. }
  87. iface.link.state = state
  88. }
  89. /*
  90. Free the OS structures.
  91. */
  92. os._freeifaddrs(head)
  93. /*
  94. Turn the map into a slice to return.
  95. */
  96. _interfaces := make([dynamic]Network_Interface, 0, allocator)
  97. for _, iface in ifaces {
  98. append(&_interfaces, iface^)
  99. free(iface)
  100. }
  101. return _interfaces[:], {}
  102. }