sys_freebsd.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. // Copyright 2016 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package route
  5. import (
  6. "syscall"
  7. "unsafe"
  8. )
  9. func (typ RIBType) parseable() bool { return true }
  10. // RouteMetrics represents route metrics.
  11. type RouteMetrics struct {
  12. PathMTU int // path maximum transmission unit
  13. }
  14. // SysType implements the SysType method of Sys interface.
  15. func (rmx *RouteMetrics) SysType() SysType { return SysMetrics }
  16. // Sys implements the Sys method of Message interface.
  17. func (m *RouteMessage) Sys() []Sys {
  18. if kernelAlign == 8 {
  19. return []Sys{
  20. &RouteMetrics{
  21. PathMTU: int(nativeEndian.Uint64(m.raw[m.extOff+8 : m.extOff+16])),
  22. },
  23. }
  24. }
  25. return []Sys{
  26. &RouteMetrics{
  27. PathMTU: int(nativeEndian.Uint32(m.raw[m.extOff+4 : m.extOff+8])),
  28. },
  29. }
  30. }
  31. // InterfaceMetrics represents interface metrics.
  32. type InterfaceMetrics struct {
  33. Type int // interface type
  34. MTU int // maximum transmission unit
  35. }
  36. // SysType implements the SysType method of Sys interface.
  37. func (imx *InterfaceMetrics) SysType() SysType { return SysMetrics }
  38. // Sys implements the Sys method of Message interface.
  39. func (m *InterfaceMessage) Sys() []Sys {
  40. return []Sys{
  41. &InterfaceMetrics{
  42. Type: int(m.raw[m.extOff]),
  43. MTU: int(nativeEndian.Uint32(m.raw[m.extOff+8 : m.extOff+12])),
  44. },
  45. }
  46. }
  47. var compatFreeBSD32 bool // 386 emulation on amd64
  48. func probeRoutingStack() (int, map[int]*wireFormat) {
  49. var p uintptr
  50. wordSize := int(unsafe.Sizeof(p))
  51. align := wordSize
  52. // In the case of kern.supported_archs="amd64 i386", we need
  53. // to know the underlying kernel's architecture because the
  54. // alignment for routing facilities are set at the build time
  55. // of the kernel.
  56. conf, _ := syscall.Sysctl("kern.conftxt")
  57. for i, j := 0, 0; j < len(conf); j++ {
  58. if conf[j] != '\n' {
  59. continue
  60. }
  61. s := conf[i:j]
  62. i = j + 1
  63. if len(s) > len("machine") && s[:len("machine")] == "machine" {
  64. s = s[len("machine"):]
  65. for k := 0; k < len(s); k++ {
  66. if s[k] == ' ' || s[k] == '\t' {
  67. s = s[1:]
  68. }
  69. break
  70. }
  71. if s == "amd64" {
  72. align = 8
  73. }
  74. break
  75. }
  76. }
  77. if align != wordSize {
  78. compatFreeBSD32 = true // 386 emulation on amd64
  79. }
  80. var rtm, ifm, ifam, ifmam, ifanm *wireFormat
  81. if compatFreeBSD32 {
  82. rtm = &wireFormat{extOff: sizeofRtMsghdrFreeBSD10Emu - sizeofRtMetricsFreeBSD10Emu, bodyOff: sizeofRtMsghdrFreeBSD10Emu}
  83. ifm = &wireFormat{extOff: 16}
  84. ifam = &wireFormat{extOff: sizeofIfaMsghdrFreeBSD10Emu, bodyOff: sizeofIfaMsghdrFreeBSD10Emu}
  85. ifmam = &wireFormat{extOff: sizeofIfmaMsghdrFreeBSD10Emu, bodyOff: sizeofIfmaMsghdrFreeBSD10Emu}
  86. ifanm = &wireFormat{extOff: sizeofIfAnnouncemsghdrFreeBSD10Emu, bodyOff: sizeofIfAnnouncemsghdrFreeBSD10Emu}
  87. } else {
  88. rtm = &wireFormat{extOff: sizeofRtMsghdrFreeBSD10 - sizeofRtMetricsFreeBSD10, bodyOff: sizeofRtMsghdrFreeBSD10}
  89. ifm = &wireFormat{extOff: 16}
  90. ifam = &wireFormat{extOff: sizeofIfaMsghdrFreeBSD10, bodyOff: sizeofIfaMsghdrFreeBSD10}
  91. ifmam = &wireFormat{extOff: sizeofIfmaMsghdrFreeBSD10, bodyOff: sizeofIfmaMsghdrFreeBSD10}
  92. ifanm = &wireFormat{extOff: sizeofIfAnnouncemsghdrFreeBSD10, bodyOff: sizeofIfAnnouncemsghdrFreeBSD10}
  93. }
  94. rel, _ := syscall.SysctlUint32("kern.osreldate")
  95. switch {
  96. case rel < 800000:
  97. if compatFreeBSD32 {
  98. ifm.bodyOff = sizeofIfMsghdrFreeBSD7Emu
  99. } else {
  100. ifm.bodyOff = sizeofIfMsghdrFreeBSD7
  101. }
  102. case 800000 <= rel && rel < 900000:
  103. if compatFreeBSD32 {
  104. ifm.bodyOff = sizeofIfMsghdrFreeBSD8Emu
  105. } else {
  106. ifm.bodyOff = sizeofIfMsghdrFreeBSD8
  107. }
  108. case 900000 <= rel && rel < 1000000:
  109. if compatFreeBSD32 {
  110. ifm.bodyOff = sizeofIfMsghdrFreeBSD9Emu
  111. } else {
  112. ifm.bodyOff = sizeofIfMsghdrFreeBSD9
  113. }
  114. case 1000000 <= rel && rel < 1100000:
  115. if compatFreeBSD32 {
  116. ifm.bodyOff = sizeofIfMsghdrFreeBSD10Emu
  117. } else {
  118. ifm.bodyOff = sizeofIfMsghdrFreeBSD10
  119. }
  120. default:
  121. if compatFreeBSD32 {
  122. ifm.bodyOff = sizeofIfMsghdrFreeBSD11Emu
  123. } else {
  124. ifm.bodyOff = sizeofIfMsghdrFreeBSD11
  125. }
  126. if rel >= 1102000 { // see https://github.com/freebsd/freebsd/commit/027c7f4d66ff8d8c4a46c3665a5ee7d6d8462034#diff-ad4e5b7f1449ea3fc87bc97280de145b
  127. align = wordSize
  128. }
  129. }
  130. rtm.parse = rtm.parseRouteMessage
  131. ifm.parse = ifm.parseInterfaceMessage
  132. ifam.parse = ifam.parseInterfaceAddrMessage
  133. ifmam.parse = ifmam.parseInterfaceMulticastAddrMessage
  134. ifanm.parse = ifanm.parseInterfaceAnnounceMessage
  135. return align, map[int]*wireFormat{
  136. sysRTM_ADD: rtm,
  137. sysRTM_DELETE: rtm,
  138. sysRTM_CHANGE: rtm,
  139. sysRTM_GET: rtm,
  140. sysRTM_LOSING: rtm,
  141. sysRTM_REDIRECT: rtm,
  142. sysRTM_MISS: rtm,
  143. sysRTM_LOCK: rtm,
  144. sysRTM_RESOLVE: rtm,
  145. sysRTM_NEWADDR: ifam,
  146. sysRTM_DELADDR: ifam,
  147. sysRTM_IFINFO: ifm,
  148. sysRTM_NEWMADDR: ifmam,
  149. sysRTM_DELMADDR: ifmam,
  150. sysRTM_IFANNOUNCE: ifanm,
  151. }
  152. }