interface_linux.odin 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. package net
  2. //+build linux
  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. This file uses `getifaddrs` libc call to enumerate interfaces.
  19. TODO: When we have raw sockets, split off into its own file for Linux so we can use the NETLINK protocol and bypass libc.
  20. */
  21. //import "core:strings"
  22. // TODO(flysand): regression
  23. // NOTE(flysand): https://man7.org/linux/man-pages/man7/netlink.7.html
  24. // apparently musl libc uses this to enumerate network interfaces
  25. @(private)
  26. _enumerate_interfaces :: proc(allocator := context.allocator) -> (interfaces: []Network_Interface, err: Network_Error) {
  27. context.allocator = allocator
  28. // head: ^os.ifaddrs
  29. // if res := os._getifaddrs(&head); res < 0 {
  30. // return {}, .Unable_To_Enumerate_Network_Interfaces
  31. // }
  32. // /*
  33. // Unlike Windows, *nix regrettably doesn't return all it knows about an interface in one big struct.
  34. // We're going to have to iterate over a list and coalesce information as we go.
  35. // */
  36. // ifaces: map[string]^Network_Interface
  37. // defer delete(ifaces)
  38. // for ifaddr := head; ifaddr != nil; ifaddr = ifaddr.next {
  39. // adapter_name := string(ifaddr.name)
  40. // /*
  41. // Check if we have seen this interface name before so we can reuse the `Network_Interface`.
  42. // Else, create a new one.
  43. // */
  44. // if adapter_name not_in ifaces {
  45. // ifaces[adapter_name] = new(Network_Interface)
  46. // ifaces[adapter_name].adapter_name = strings.clone(adapter_name)
  47. // }
  48. // iface := ifaces[adapter_name]
  49. // address: Address
  50. // netmask: Netmask
  51. // if ifaddr.address != nil {
  52. // switch int(ifaddr.address.sa_family) {
  53. // case os.AF_INET, os.AF_INET6:
  54. // address = _sockaddr_basic_to_endpoint(ifaddr.address).address
  55. // case os.AF_PACKET:
  56. // /*
  57. // For some obscure reason the 64-bit `getifaddrs` call returns a pointer to a
  58. // 32-bit `RTNL_LINK_STATS` structure, which of course means that tx/rx byte count
  59. // is truncated beyond usefulness.
  60. // We're not going to retrieve stats now. Instead this serves as a reminder to use
  61. // the NETLINK protocol for this purpose.
  62. // But in case you were curious:
  63. // stats := transmute(^os.rtnl_link_stats)ifaddr.data
  64. // fmt.println(stats)
  65. // */
  66. // case:
  67. // }
  68. // }
  69. // if ifaddr.netmask != nil {
  70. // switch int(ifaddr.netmask.sa_family) {
  71. // case os.AF_INET, os.AF_INET6:
  72. // netmask = Netmask(_sockaddr_basic_to_endpoint(ifaddr.netmask).address)
  73. // case:
  74. // }
  75. // }
  76. // if ifaddr.broadcast_or_dest != nil && .BROADCAST in ifaddr.flags {
  77. // switch int(ifaddr.broadcast_or_dest.sa_family) {
  78. // case os.AF_INET, os.AF_INET6:
  79. // broadcast := _sockaddr_basic_to_endpoint(ifaddr.broadcast_or_dest).address
  80. // append(&iface.multicast, broadcast)
  81. // case:
  82. // }
  83. // }
  84. // if address != nil {
  85. // lease := Lease{
  86. // address = address,
  87. // netmask = netmask,
  88. // }
  89. // append(&iface.unicast, lease)
  90. // }
  91. // /*
  92. // TODO: Refine this based on the type of adapter.
  93. // */
  94. // state := Link_State{}
  95. // if .UP in ifaddr.flags {
  96. // state |= {.Up}
  97. // }
  98. // if .DORMANT in ifaddr.flags {
  99. // state |= {.Dormant}
  100. // }
  101. // if .LOOPBACK in ifaddr.flags {
  102. // state |= {.Loopback}
  103. // }
  104. // iface.link.state = state
  105. // }
  106. // /*
  107. // Free the OS structures.
  108. // */
  109. // os._freeifaddrs(head)
  110. // /*
  111. // Turn the map into a slice to return.
  112. // */
  113. // _interfaces := make([dynamic]Network_Interface, 0, allocator)
  114. // for _, iface in ifaces {
  115. // append(&_interfaces, iface^)
  116. // free(iface)
  117. // }
  118. // return _interfaces[:], {}
  119. return nil, {}
  120. }