interface_darwin.odin 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. #+build darwin
  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 "core:strings"
  20. import "core:sys/posix"
  21. foreign import lib "system:System"
  22. @(private)
  23. _enumerate_interfaces :: proc(allocator := context.allocator) -> (interfaces: []Network_Interface, err: Interfaces_Error) {
  24. context.allocator = allocator
  25. head: ^ifaddrs
  26. if getifaddrs(&head) != .OK {
  27. return {}, .Unable_To_Enumerate_Network_Interfaces
  28. }
  29. defer freeifaddrs(head)
  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. key_ptr, iface, inserted, mem_err := map_entry(&ifaces, adapter_name)
  35. if mem_err == nil && inserted {
  36. key_ptr^, mem_err = strings.clone(adapter_name)
  37. iface.adapter_name = key_ptr^
  38. }
  39. if mem_err != nil {
  40. return {}, .Allocation_Failure
  41. }
  42. address: Address
  43. netmask: Netmask
  44. if ifaddr.addr != nil {
  45. #partial switch ifaddr.addr.sa_family {
  46. case .INET, .INET6:
  47. address = _sockaddr_basic_to_endpoint(ifaddr.addr).address
  48. }
  49. }
  50. if ifaddr.netmask != nil {
  51. #partial switch ifaddr.netmask.sa_family {
  52. case .INET, .INET6:
  53. netmask = Netmask(_sockaddr_basic_to_endpoint(ifaddr.netmask).address)
  54. }
  55. }
  56. if ifaddr.dstaddr != nil && .BROADCAST in ifaddr.flags {
  57. #partial switch ifaddr.dstaddr.sa_family {
  58. case .INET, .INET6:
  59. broadcast := _sockaddr_basic_to_endpoint(ifaddr.dstaddr).address
  60. append(&iface.multicast, broadcast)
  61. }
  62. }
  63. if address != nil {
  64. lease := Lease{
  65. address = address,
  66. netmask = netmask,
  67. }
  68. append(&iface.unicast, lease)
  69. }
  70. /*
  71. TODO: Refine this based on the type of adapter.
  72. */
  73. state := Link_State{}
  74. if .UP in ifaddr.flags {
  75. state += {.Up}
  76. }
  77. /*if .DORMANT in ifaddr.flags {
  78. state |= {.Dormant}
  79. }*/
  80. if .LOOPBACK in ifaddr.flags {
  81. state += {.Loopback}
  82. }
  83. iface.link.state = state
  84. }
  85. interfaces = make([]Network_Interface, len(ifaces))
  86. i: int
  87. for _, iface in ifaces {
  88. interfaces[i] = iface
  89. i += 1
  90. }
  91. return interfaces, nil
  92. }
  93. @(private)
  94. IF_Flag :: enum u32 {
  95. UP,
  96. BROADCAST,
  97. DEBUG,
  98. LOOPBACK,
  99. POINTTOPOINT,
  100. NOTRAILERS,
  101. RUNNING,
  102. NOARP,
  103. PROMISC,
  104. ALLMULTI,
  105. OACTIVE,
  106. SIMPLEX,
  107. LINK0,
  108. LINK1,
  109. LINK2,
  110. MULTICAST,
  111. }
  112. @(private)
  113. IF_Flags :: bit_set[IF_Flag; u32]
  114. @(private)
  115. ifaddrs :: struct {
  116. next: ^ifaddrs,
  117. name: cstring,
  118. flags: IF_Flags,
  119. addr: ^posix.sockaddr,
  120. netmask: ^posix.sockaddr,
  121. dstaddr: ^posix.sockaddr,
  122. data: rawptr,
  123. }
  124. @(private)
  125. foreign lib {
  126. getifaddrs :: proc(ifap: ^^ifaddrs) -> posix.result ---
  127. freeifaddrs :: proc(ifp: ^ifaddrs) ---
  128. }