Home | History | Annotate | Download | only in route
      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