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