You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

155 lines
4.6 KiB

  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. func probeRoutingStack() (int, map[int]*wireFormat) {
  48. var p uintptr
  49. wordSize := int(unsafe.Sizeof(p))
  50. align := int(unsafe.Sizeof(p))
  51. // In the case of kern.supported_archs="amd64 i386", we need
  52. // to know the underlying kernel's architecture because the
  53. // alignment for routing facilities are set at the build time
  54. // of the kernel.
  55. conf, _ := syscall.Sysctl("kern.conftxt")
  56. for i, j := 0, 0; j < len(conf); j++ {
  57. if conf[j] != '\n' {
  58. continue
  59. }
  60. s := conf[i:j]
  61. i = j + 1
  62. if len(s) > len("machine") && s[:len("machine")] == "machine" {
  63. s = s[len("machine"):]
  64. for k := 0; k < len(s); k++ {
  65. if s[k] == ' ' || s[k] == '\t' {
  66. s = s[1:]
  67. }
  68. break
  69. }
  70. if s == "amd64" {
  71. align = 8
  72. }
  73. break
  74. }
  75. }
  76. var rtm, ifm, ifam, ifmam, ifanm *wireFormat
  77. if align != wordSize { // 386 emulation on amd64
  78. rtm = &wireFormat{extOff: sizeofRtMsghdrFreeBSD10Emu - sizeofRtMetricsFreeBSD10Emu, bodyOff: sizeofRtMsghdrFreeBSD10Emu}
  79. ifm = &wireFormat{extOff: 16}
  80. ifam = &wireFormat{extOff: sizeofIfaMsghdrFreeBSD10Emu, bodyOff: sizeofIfaMsghdrFreeBSD10Emu}
  81. ifmam = &wireFormat{extOff: sizeofIfmaMsghdrFreeBSD10Emu, bodyOff: sizeofIfmaMsghdrFreeBSD10Emu}
  82. ifanm = &wireFormat{extOff: sizeofIfAnnouncemsghdrFreeBSD10Emu, bodyOff: sizeofIfAnnouncemsghdrFreeBSD10Emu}
  83. } else {
  84. rtm = &wireFormat{extOff: sizeofRtMsghdrFreeBSD10 - sizeofRtMetricsFreeBSD10, bodyOff: sizeofRtMsghdrFreeBSD10}
  85. ifm = &wireFormat{extOff: 16}
  86. ifam = &wireFormat{extOff: sizeofIfaMsghdrFreeBSD10, bodyOff: sizeofIfaMsghdrFreeBSD10}
  87. ifmam = &wireFormat{extOff: sizeofIfmaMsghdrFreeBSD10, bodyOff: sizeofIfmaMsghdrFreeBSD10}
  88. ifanm = &wireFormat{extOff: sizeofIfAnnouncemsghdrFreeBSD10, bodyOff: sizeofIfAnnouncemsghdrFreeBSD10}
  89. }
  90. rel, _ := syscall.SysctlUint32("kern.osreldate")
  91. switch {
  92. case rel < 800000:
  93. if align != wordSize { // 386 emulation on amd64
  94. ifm.bodyOff = sizeofIfMsghdrFreeBSD7Emu
  95. } else {
  96. ifm.bodyOff = sizeofIfMsghdrFreeBSD7
  97. }
  98. case 800000 <= rel && rel < 900000:
  99. if align != wordSize { // 386 emulation on amd64
  100. ifm.bodyOff = sizeofIfMsghdrFreeBSD8Emu
  101. } else {
  102. ifm.bodyOff = sizeofIfMsghdrFreeBSD8
  103. }
  104. case 900000 <= rel && rel < 1000000:
  105. if align != wordSize { // 386 emulation on amd64
  106. ifm.bodyOff = sizeofIfMsghdrFreeBSD9Emu
  107. } else {
  108. ifm.bodyOff = sizeofIfMsghdrFreeBSD9
  109. }
  110. case 1000000 <= rel && rel < 1100000:
  111. if align != wordSize { // 386 emulation on amd64
  112. ifm.bodyOff = sizeofIfMsghdrFreeBSD10Emu
  113. } else {
  114. ifm.bodyOff = sizeofIfMsghdrFreeBSD10
  115. }
  116. default:
  117. if align != wordSize { // 386 emulation on amd64
  118. ifm.bodyOff = sizeofIfMsghdrFreeBSD11Emu
  119. } else {
  120. ifm.bodyOff = sizeofIfMsghdrFreeBSD11
  121. }
  122. }
  123. rtm.parse = rtm.parseRouteMessage
  124. ifm.parse = ifm.parseInterfaceMessage
  125. ifam.parse = ifam.parseInterfaceAddrMessage
  126. ifmam.parse = ifmam.parseInterfaceMulticastAddrMessage
  127. ifanm.parse = ifanm.parseInterfaceAnnounceMessage
  128. return align, map[int]*wireFormat{
  129. sysRTM_ADD: rtm,
  130. sysRTM_DELETE: rtm,
  131. sysRTM_CHANGE: rtm,
  132. sysRTM_GET: rtm,
  133. sysRTM_LOSING: rtm,
  134. sysRTM_REDIRECT: rtm,
  135. sysRTM_MISS: rtm,
  136. sysRTM_LOCK: rtm,
  137. sysRTM_RESOLVE: rtm,
  138. sysRTM_NEWADDR: ifam,
  139. sysRTM_DELADDR: ifam,
  140. sysRTM_IFINFO: ifm,
  141. sysRTM_NEWMADDR: ifmam,
  142. sysRTM_DELMADDR: ifmam,
  143. sysRTM_IFANNOUNCE: ifanm,
  144. }
  145. }