mirror of
https://github.com/kubenetworks/kubevpn.git
synced 2025-10-15 11:50:47 +08:00
feat: add vendor
This commit is contained in:
29
vendor/github.com/libp2p/go-netroute/LICENSE
generated
vendored
Normal file
29
vendor/github.com/libp2p/go-netroute/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
Copyright (c) 2020 Will Scott. All rights reserved.
|
||||
Copyright (c) 2012 Google, Inc. All rights reserved.
|
||||
Copyright (c) 2009-2011 Andreas Krennmair. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Andreas Krennmair, Google, nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
60
vendor/github.com/libp2p/go-netroute/README.md
generated
vendored
Normal file
60
vendor/github.com/libp2p/go-netroute/README.md
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
Go Netroute
|
||||
===
|
||||
|
||||
[](http://protocol.ai)
|
||||
[](http://github.com/libp2p/libp2p)
|
||||
[](https://travis-ci.com/libp2p/go-netroute)
|
||||
|
||||
A cross-platform implementation of the [`gopacket/routing.Router`](https://godoc.org/github.com/google/gopacket/routing#Router) interface.
|
||||
|
||||
This library is derived from `gopacket` for linux, `x/net/route` for mac, and `iphlpapi.dll` for windows.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Install](#install)
|
||||
- [Usage](#usage)
|
||||
- [Documentation](#documentation)
|
||||
- [Contribute](#contribute)
|
||||
- [License](#license)
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
go get github.com/libp2p/go-netroute
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
To be used for querying the local OS routing table.
|
||||
|
||||
```go
|
||||
import (
|
||||
netroute "github.com/libp2p/go-netroute"
|
||||
)
|
||||
|
||||
func main() {
|
||||
r, err := netroute.New()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
iface, gw, src, err := r.Route(net.IPv4(127, 0, 0, 1))
|
||||
fmt.Printf("%v, %v, %v, %v\n", iface, gw, src, err)
|
||||
}
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
See the [gopacket](https://github.com/google/gopacket/blob/master/routing/) interface for thoughts on design,
|
||||
and [godoc](https://godoc.org/github.com/libp2p/go-netroute) for API documentation.
|
||||
|
||||
## Contribute
|
||||
|
||||
Contributions welcome. Please check out [the issues](https://github.com/libp2p/go-netroute/issues).
|
||||
|
||||
Check out our [contributing document](https://github.com/libp2p/community/blob/master/contributing.md) for more information on how we work, and about contributing in general. Please be aware that all interactions related to multiformats are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).
|
||||
|
||||
Small note: If editing the README, please conform to the [standard-readme](https://github.com/RichardLitt/standard-readme) specification.
|
||||
|
||||
## License
|
||||
|
||||
[BSD](LICENSE) © Will Scott, and the Gopacket authors (i.e. Google)
|
161
vendor/github.com/libp2p/go-netroute/common.go
generated
vendored
Normal file
161
vendor/github.com/libp2p/go-netroute/common.go
generated
vendored
Normal file
@@ -0,0 +1,161 @@
|
||||
// Copyright 2012 Google, Inc. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file in the root of the source
|
||||
// tree.
|
||||
|
||||
// Originally found in
|
||||
// https://github.com/google/gopacket/blob/master/routing/routing.go
|
||||
// - Route selection modified to choose most selective route
|
||||
// to break ties when route priority is insufficient.
|
||||
package netroute
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// rtInfo contains information on a single route.
|
||||
type rtInfo struct {
|
||||
Src, Dst *net.IPNet
|
||||
Gateway, PrefSrc net.IP
|
||||
// We currently ignore the InputIface.
|
||||
InputIface, OutputIface uint32
|
||||
Priority uint32
|
||||
}
|
||||
|
||||
func (rt rtInfo) IsMoreSpecThan(mostSpecificRt *rtInfo) bool {
|
||||
if mostSpecificRt == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
var candSpec, curSpec int
|
||||
if rt.Dst != nil {
|
||||
candSpec, _ = rt.Dst.Mask.Size()
|
||||
}
|
||||
if mostSpecificRt.Dst != nil {
|
||||
curSpec, _ = mostSpecificRt.Dst.Mask.Size()
|
||||
}
|
||||
|
||||
if candSpec > curSpec {
|
||||
return true
|
||||
} else if candSpec < curSpec {
|
||||
return false
|
||||
}
|
||||
|
||||
// Windows and MacOS hasn't metric/priority on rule entry,
|
||||
// But the interface device has the priority property.
|
||||
//
|
||||
// Before we find more correctly way on different OS platform,
|
||||
// we keep the same rule selecting logical as before which
|
||||
// is more later more special
|
||||
return mostSpecificRt.Priority >= rt.Priority
|
||||
}
|
||||
|
||||
// routeSlice implements sort.Interface to sort routes by Priority.
|
||||
type routeSlice []*rtInfo
|
||||
|
||||
func (r routeSlice) Len() int {
|
||||
return len(r)
|
||||
}
|
||||
func (r routeSlice) Less(i, j int) bool {
|
||||
return r[i].Priority < r[j].Priority
|
||||
}
|
||||
func (r routeSlice) Swap(i, j int) {
|
||||
r[i], r[j] = r[j], r[i]
|
||||
}
|
||||
|
||||
type router struct {
|
||||
ifaces map[int]net.Interface
|
||||
addrs map[int]ipAddrs
|
||||
v4, v6 routeSlice
|
||||
}
|
||||
|
||||
func (r *router) String() string {
|
||||
strs := []string{"ROUTER", "--- V4 ---"}
|
||||
for _, route := range r.v4 {
|
||||
strs = append(strs, fmt.Sprintf("%+v", *route))
|
||||
}
|
||||
strs = append(strs, "--- V6 ---")
|
||||
for _, route := range r.v6 {
|
||||
strs = append(strs, fmt.Sprintf("%+v", *route))
|
||||
}
|
||||
return strings.Join(strs, "\n")
|
||||
}
|
||||
|
||||
type ipAddrs struct {
|
||||
v4, v6 net.IP
|
||||
}
|
||||
|
||||
func (r *router) Route(dst net.IP) (iface *net.Interface, gateway, preferredSrc net.IP, err error) {
|
||||
return r.RouteWithSrc(nil, nil, dst)
|
||||
}
|
||||
|
||||
func (r *router) RouteWithSrc(input net.HardwareAddr, src, dst net.IP) (iface *net.Interface, gateway, preferredSrc net.IP, err error) {
|
||||
var ifaceIndex int
|
||||
switch {
|
||||
case dst.To4() != nil:
|
||||
ifaceIndex, gateway, preferredSrc, err = r.route(r.v4, input, src, dst)
|
||||
case dst.To16() != nil:
|
||||
ifaceIndex, gateway, preferredSrc, err = r.route(r.v6, input, src, dst)
|
||||
default:
|
||||
err = errors.New("IP is not valid as IPv4 or IPv6")
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Interfaces are 1-indexed, but we store them in a 0-indexed array.
|
||||
correspondingIface, ok := r.ifaces[ifaceIndex]
|
||||
if !ok {
|
||||
err = errors.New("Route refereced unknown interface")
|
||||
}
|
||||
iface = &correspondingIface
|
||||
|
||||
if preferredSrc == nil {
|
||||
switch {
|
||||
case dst.To4() != nil:
|
||||
preferredSrc = r.addrs[ifaceIndex].v4
|
||||
case dst.To16() != nil:
|
||||
preferredSrc = r.addrs[ifaceIndex].v6
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (r *router) route(routes routeSlice, input net.HardwareAddr, src, dst net.IP) (iface int, gateway, preferredSrc net.IP, err error) {
|
||||
var inputIndex uint32
|
||||
if input != nil {
|
||||
for i, iface := range r.ifaces {
|
||||
if bytes.Equal(input, iface.HardwareAddr) {
|
||||
// Convert from zero- to one-indexed.
|
||||
inputIndex = uint32(i + 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
var mostSpecificRt *rtInfo
|
||||
for _, rt := range routes {
|
||||
if rt.InputIface != 0 && rt.InputIface != inputIndex {
|
||||
continue
|
||||
}
|
||||
if src != nil && rt.Src != nil && !rt.Src.Contains(src) {
|
||||
continue
|
||||
}
|
||||
if rt.Dst != nil && !rt.Dst.Contains(dst) {
|
||||
continue
|
||||
}
|
||||
if rt.IsMoreSpecThan(mostSpecificRt) {
|
||||
mostSpecificRt = rt
|
||||
}
|
||||
}
|
||||
if mostSpecificRt != nil {
|
||||
return int(mostSpecificRt.OutputIface), mostSpecificRt.Gateway, mostSpecificRt.PrefSrc, nil
|
||||
}
|
||||
err = fmt.Errorf("no route found for %v", dst)
|
||||
return
|
||||
}
|
152
vendor/github.com/libp2p/go-netroute/netroute_bsd.go
generated
vendored
Normal file
152
vendor/github.com/libp2p/go-netroute/netroute_bsd.go
generated
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
// Copyright 2012 Google, Inc. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file in the root of the source
|
||||
// tree.
|
||||
|
||||
//go:build darwin || dragonfly || freebsd || netbsd || openbsd
|
||||
|
||||
// This is a BSD import for the routing structure initially found in
|
||||
// https://github.com/google/gopacket/blob/master/routing/routing.go
|
||||
// RIB parsing follows the BSD route format described in
|
||||
// https://github.com/freebsd/freebsd/blob/master/sys/net/route.h
|
||||
package netroute
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"sort"
|
||||
"syscall"
|
||||
|
||||
"github.com/google/gopacket/routing"
|
||||
"golang.org/x/net/route"
|
||||
)
|
||||
|
||||
func toIPAddr(a route.Addr) (net.IP, error) {
|
||||
switch t := a.(type) {
|
||||
case *route.Inet4Addr:
|
||||
ip := net.IPv4(t.IP[0], t.IP[1], t.IP[2], t.IP[3])
|
||||
return ip, nil
|
||||
case *route.Inet6Addr:
|
||||
ip := make(net.IP, net.IPv6len)
|
||||
copy(ip, t.IP[:])
|
||||
return ip, nil
|
||||
default:
|
||||
return net.IP{}, fmt.Errorf("unknown family: %v", t)
|
||||
}
|
||||
}
|
||||
|
||||
// selected BSD Route flags.
|
||||
const (
|
||||
RTF_UP = 0x1
|
||||
RTF_GATEWAY = 0x2
|
||||
RTF_HOST = 0x4
|
||||
RTF_REJECT = 0x8
|
||||
RTF_DYNAMIC = 0x10
|
||||
RTF_MODIFIED = 0x20
|
||||
RTF_STATIC = 0x800
|
||||
RTF_BLACKHOLE = 0x1000
|
||||
RTF_LOCAL = 0x200000
|
||||
RTF_BROADCAST = 0x400000
|
||||
RTF_MULTICAST = 0x800000
|
||||
)
|
||||
|
||||
func New() (routing.Router, error) {
|
||||
rtr := &router{}
|
||||
rtr.ifaces = make(map[int]net.Interface)
|
||||
rtr.addrs = make(map[int]ipAddrs)
|
||||
tab, err := route.FetchRIB(syscall.AF_UNSPEC, route.RIBTypeRoute, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
msgs, err := route.ParseRIB(route.RIBTypeRoute, tab)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var ipn *net.IPNet
|
||||
for _, msg := range msgs {
|
||||
m := msg.(*route.RouteMessage)
|
||||
// We ignore the error (m.Err) here. It's not clear what this error actually means,
|
||||
// and it makes us miss routes that _should_ be included.
|
||||
routeInfo := new(rtInfo)
|
||||
|
||||
if m.Version < 3 || m.Version > 5 {
|
||||
return nil, fmt.Errorf("unexpected RIB message version: %d", m.Version)
|
||||
}
|
||||
if m.Type != 4 /* RTM_GET */ {
|
||||
return nil, fmt.Errorf("unexpected RIB message type: %d", m.Type)
|
||||
}
|
||||
|
||||
if m.Flags&RTF_UP == 0 ||
|
||||
m.Flags&(RTF_REJECT|RTF_BLACKHOLE) != 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
dst, err := toIPAddr(m.Addrs[0])
|
||||
if err == nil {
|
||||
mask, _ := toIPAddr(m.Addrs[2])
|
||||
if mask == nil {
|
||||
mask = net.IP(net.CIDRMask(0, 8*len(dst)))
|
||||
}
|
||||
ipn = &net.IPNet{IP: dst, Mask: net.IPMask(mask)}
|
||||
if m.Flags&RTF_HOST != 0 {
|
||||
ipn.Mask = net.CIDRMask(8*len(ipn.IP), 8*len(ipn.IP))
|
||||
}
|
||||
routeInfo.Dst = ipn
|
||||
} else {
|
||||
return nil, fmt.Errorf("unexpected RIB destination: %v", err)
|
||||
}
|
||||
|
||||
if m.Flags&RTF_GATEWAY != 0 {
|
||||
if gw, err := toIPAddr(m.Addrs[1]); err == nil {
|
||||
routeInfo.Gateway = gw
|
||||
}
|
||||
}
|
||||
if src, err := toIPAddr(m.Addrs[5]); err == nil {
|
||||
ipn = &net.IPNet{IP: src, Mask: net.CIDRMask(8*len(src), 8*len(src))}
|
||||
routeInfo.Src = ipn
|
||||
routeInfo.PrefSrc = src
|
||||
if m.Flags&0x2 != 0 /* RTF_GATEWAY */ {
|
||||
routeInfo.Src.Mask = net.CIDRMask(0, 8*len(routeInfo.Src.IP))
|
||||
}
|
||||
}
|
||||
routeInfo.OutputIface = uint32(m.Index)
|
||||
|
||||
switch m.Addrs[0].(type) {
|
||||
case *route.Inet4Addr:
|
||||
rtr.v4 = append(rtr.v4, routeInfo)
|
||||
case *route.Inet6Addr:
|
||||
rtr.v6 = append(rtr.v6, routeInfo)
|
||||
}
|
||||
}
|
||||
sort.Sort(rtr.v4)
|
||||
sort.Sort(rtr.v6)
|
||||
ifaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, iface := range ifaces {
|
||||
rtr.ifaces[iface.Index] = iface
|
||||
var addrs ipAddrs
|
||||
ifaceAddrs, err := iface.Addrs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, addr := range ifaceAddrs {
|
||||
if inet, ok := addr.(*net.IPNet); ok {
|
||||
// Go has a nasty habit of giving you IPv4s as ::ffff:1.2.3.4 instead of 1.2.3.4.
|
||||
// We want to use mapped v4 addresses as v4 preferred addresses, never as v6
|
||||
// preferred addresses.
|
||||
if v4 := inet.IP.To4(); v4 != nil {
|
||||
if addrs.v4 == nil {
|
||||
addrs.v4 = v4
|
||||
}
|
||||
} else if addrs.v6 == nil {
|
||||
addrs.v6 = inet.IP
|
||||
}
|
||||
}
|
||||
}
|
||||
rtr.addrs[iface.Index] = addrs
|
||||
}
|
||||
return rtr, nil
|
||||
}
|
127
vendor/github.com/libp2p/go-netroute/netroute_linux.go
generated
vendored
Normal file
127
vendor/github.com/libp2p/go-netroute/netroute_linux.go
generated
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
// Copyright 2012 Google, Inc. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file in the root of the source
|
||||
// tree.
|
||||
|
||||
//go:build linux
|
||||
|
||||
// Generate a local routing table structure following the code at
|
||||
// https://github.com/google/gopacket/blob/master/routing/routing.go
|
||||
|
||||
package netroute
|
||||
|
||||
import (
|
||||
"net"
|
||||
"sort"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/google/gopacket/routing"
|
||||
)
|
||||
|
||||
// Pulled from http://man7.org/linux/man-pages/man7/rtnetlink.7.html
|
||||
// See the section on RTM_NEWROUTE, specifically 'struct rtmsg'.
|
||||
type routeInfoInMemory struct {
|
||||
Family byte
|
||||
DstLen byte
|
||||
SrcLen byte
|
||||
TOS byte
|
||||
|
||||
Table byte
|
||||
Protocol byte
|
||||
Scope byte
|
||||
Type byte
|
||||
|
||||
Flags uint32
|
||||
}
|
||||
|
||||
func New() (routing.Router, error) {
|
||||
rtr := &router{}
|
||||
rtr.ifaces = make(map[int]net.Interface)
|
||||
rtr.addrs = make(map[int]ipAddrs)
|
||||
tab, err := syscall.NetlinkRIB(syscall.RTM_GETROUTE, syscall.AF_UNSPEC)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
msgs, err := syscall.ParseNetlinkMessage(tab)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
loop:
|
||||
for _, m := range msgs {
|
||||
switch m.Header.Type {
|
||||
case syscall.NLMSG_DONE:
|
||||
break loop
|
||||
case syscall.RTM_NEWROUTE:
|
||||
rt := (*routeInfoInMemory)(unsafe.Pointer(&m.Data[0]))
|
||||
routeInfo := rtInfo{}
|
||||
attrs, err := syscall.ParseNetlinkRouteAttr(&m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch rt.Family {
|
||||
case syscall.AF_INET:
|
||||
rtr.v4 = append(rtr.v4, &routeInfo)
|
||||
case syscall.AF_INET6:
|
||||
rtr.v6 = append(rtr.v6, &routeInfo)
|
||||
default:
|
||||
continue loop
|
||||
}
|
||||
for _, attr := range attrs {
|
||||
switch attr.Attr.Type {
|
||||
case syscall.RTA_DST:
|
||||
routeInfo.Dst = &net.IPNet{
|
||||
IP: net.IP(attr.Value),
|
||||
Mask: net.CIDRMask(int(rt.DstLen), len(attr.Value)*8),
|
||||
}
|
||||
case syscall.RTA_SRC:
|
||||
routeInfo.Src = &net.IPNet{
|
||||
IP: net.IP(attr.Value),
|
||||
Mask: net.CIDRMask(int(rt.SrcLen), len(attr.Value)*8),
|
||||
}
|
||||
case syscall.RTA_GATEWAY:
|
||||
routeInfo.Gateway = net.IP(attr.Value)
|
||||
case syscall.RTA_PREFSRC:
|
||||
routeInfo.PrefSrc = net.IP(attr.Value)
|
||||
case syscall.RTA_IIF:
|
||||
routeInfo.InputIface = *(*uint32)(unsafe.Pointer(&attr.Value[0]))
|
||||
case syscall.RTA_OIF:
|
||||
routeInfo.OutputIface = *(*uint32)(unsafe.Pointer(&attr.Value[0]))
|
||||
case syscall.RTA_PRIORITY:
|
||||
routeInfo.Priority = *(*uint32)(unsafe.Pointer(&attr.Value[0]))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sort.Sort(rtr.v4)
|
||||
sort.Sort(rtr.v6)
|
||||
ifaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, iface := range ifaces {
|
||||
rtr.ifaces[iface.Index] = iface
|
||||
var addrs ipAddrs
|
||||
ifaceAddrs, err := iface.Addrs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, addr := range ifaceAddrs {
|
||||
if inet, ok := addr.(*net.IPNet); ok {
|
||||
// Go has a nasty habit of giving you IPv4s as ::ffff:1.2.3.4 instead of 1.2.3.4.
|
||||
// We want to use mapped v4 addresses as v4 preferred addresses, never as v6
|
||||
// preferred addresses.
|
||||
if v4 := inet.IP.To4(); v4 != nil {
|
||||
if addrs.v4 == nil {
|
||||
addrs.v4 = v4
|
||||
}
|
||||
} else if addrs.v6 == nil {
|
||||
addrs.v6 = inet.IP
|
||||
}
|
||||
}
|
||||
}
|
||||
rtr.addrs[iface.Index] = addrs
|
||||
}
|
||||
return rtr, nil
|
||||
}
|
141
vendor/github.com/libp2p/go-netroute/netroute_plan9.go
generated
vendored
Normal file
141
vendor/github.com/libp2p/go-netroute/netroute_plan9.go
generated
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
// Generate a local routing table structure following the code at
|
||||
// https://github.com/google/gopacket/blob/master/routing/routing.go
|
||||
//
|
||||
// Plan 9 networking is described here: http://9p.io/magic/man2html/3/ip
|
||||
|
||||
package netroute
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/google/gopacket/routing"
|
||||
)
|
||||
|
||||
const netdir = "/net"
|
||||
|
||||
func New() (routing.Router, error) {
|
||||
rtr := &router{}
|
||||
rtr.ifaces = make(map[int]net.Interface)
|
||||
rtr.addrs = make(map[int]ipAddrs)
|
||||
ifaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get interfaces: %v", err)
|
||||
}
|
||||
for _, iface := range ifaces {
|
||||
rtr.ifaces[iface.Index] = iface
|
||||
var addrs ipAddrs
|
||||
ifaceAddrs, err := iface.Addrs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, addr := range ifaceAddrs {
|
||||
if inet, ok := addr.(*net.IPNet); ok {
|
||||
// Go has a nasty habit of giving you IPv4s as ::ffff:1.2.3.4 instead of 1.2.3.4.
|
||||
// We want to use mapped v4 addresses as v4 preferred addresses, never as v6
|
||||
// preferred addresses.
|
||||
if v4 := inet.IP.To4(); v4 != nil {
|
||||
if addrs.v4 == nil {
|
||||
addrs.v4 = v4
|
||||
}
|
||||
} else if addrs.v6 == nil {
|
||||
addrs.v6 = inet.IP
|
||||
}
|
||||
}
|
||||
}
|
||||
rtr.addrs[iface.Index] = addrs
|
||||
}
|
||||
|
||||
rtr.v4, rtr.v6, err = parseIPRoutes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rtr, nil
|
||||
}
|
||||
|
||||
func parseIPRoutes() (v4, v6 routeSlice, err error) {
|
||||
buf, err := ioutil.ReadFile(netdir + "/iproute")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
for {
|
||||
i := bytes.IndexRune(buf, '\n')
|
||||
if i <= 0 {
|
||||
break
|
||||
}
|
||||
f := strings.Fields(string(buf[:i]))
|
||||
buf = buf[i+1:]
|
||||
|
||||
if len(f) < 8 {
|
||||
return nil, nil, fmt.Errorf("iproute entry contains %d fields", len(f))
|
||||
}
|
||||
flags, rt, err := parseRoute(f)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if rt.Dst != nil {
|
||||
// If gateway for destination 127.0.0.1/32 is 127.0.0.1, set it to nil.
|
||||
if m, n := rt.Dst.Mask.Size(); n > 0 && m == n && rt.Dst.IP.Equal(rt.Gateway) {
|
||||
rt.Gateway = nil
|
||||
}
|
||||
}
|
||||
if strings.ContainsRune(flags, '4') { // IPv4
|
||||
v4 = append(v4, rt)
|
||||
}
|
||||
if strings.ContainsRune(flags, '6') { // IPv6
|
||||
v6 = append(v6, rt)
|
||||
}
|
||||
}
|
||||
return v4, v6, nil
|
||||
}
|
||||
|
||||
func parseRoute(f []string) (flags string, rt *rtInfo, err error) {
|
||||
rt = new(rtInfo)
|
||||
isV4 := strings.ContainsRune(f[3], '4') // flags
|
||||
|
||||
rt.PrefSrc, rt.Src, err = parsePlan9CIDR(f[6], f[7], isV4)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
_, rt.Dst, err = parsePlan9CIDR(f[0], f[1], isV4)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
rt.Gateway = net.ParseIP(f[2])
|
||||
|
||||
n, err := strconv.ParseUint(f[5], 10, 32)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
rt.InputIface = 0
|
||||
rt.OutputIface = uint32(n) + 1 // starts at 0, so net package adds 1
|
||||
rt.Priority = 0
|
||||
return f[3], rt, nil
|
||||
}
|
||||
|
||||
func parsePlan9CIDR(addr, mask string, isV4 bool) (net.IP, *net.IPNet, error) {
|
||||
if len(mask) == 0 || mask[0] != '/' {
|
||||
return nil, nil, fmt.Errorf("invalid CIDR mask %v", mask)
|
||||
}
|
||||
n, err := strconv.ParseUint(mask[1:], 10, 32)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
ip := net.ParseIP(addr)
|
||||
iplen := net.IPv6len
|
||||
if isV4 {
|
||||
// Plan 9 uses IPv6 mask for IPv4 addresses
|
||||
n -= 8 * (net.IPv6len - net.IPv4len)
|
||||
iplen = net.IPv4len
|
||||
}
|
||||
if n == 0 && ip.IsUnspecified() {
|
||||
return nil, nil, nil
|
||||
}
|
||||
m := net.CIDRMask(int(n), 8*iplen)
|
||||
return ip, &net.IPNet{IP: ip.Mask(m), Mask: m}, nil
|
||||
}
|
22
vendor/github.com/libp2p/go-netroute/netroute_stub.go
generated
vendored
Normal file
22
vendor/github.com/libp2p/go-netroute/netroute_stub.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
// A stub routing table conformant interface for js/wasm environments.
|
||||
|
||||
//go:build js && wasm
|
||||
|
||||
package netroute
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/google/gopacket/routing"
|
||||
)
|
||||
|
||||
func New() (routing.Router, error) {
|
||||
rtr := &router{}
|
||||
rtr.ifaces = make(map[int]net.Interface)
|
||||
rtr.ifaces[0] = net.Interface{}
|
||||
rtr.addrs = make(map[int]ipAddrs)
|
||||
rtr.addrs[0] = ipAddrs{}
|
||||
rtr.v4 = routeSlice{&rtInfo{}}
|
||||
rtr.v6 = routeSlice{&rtInfo{}}
|
||||
return rtr, nil
|
||||
}
|
242
vendor/github.com/libp2p/go-netroute/netroute_windows.go
generated
vendored
Normal file
242
vendor/github.com/libp2p/go-netroute/netroute_windows.go
generated
vendored
Normal file
@@ -0,0 +1,242 @@
|
||||
//go:build windows
|
||||
|
||||
package netroute
|
||||
|
||||
// Implementation Warning: mapping of the correct interface ID and index is not
|
||||
// hooked up.
|
||||
// Reference:
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/netioapi/nf-netioapi-getbestroute2
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"net"
|
||||
"unsafe"
|
||||
|
||||
"github.com/google/gopacket/routing"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
var (
|
||||
modiphlpapi = windows.NewLazyDLL("iphlpapi.dll")
|
||||
procGetBestRoute2 = modiphlpapi.NewProc("GetBestRoute2")
|
||||
)
|
||||
|
||||
type NetLUID uint64
|
||||
|
||||
type AddressPrefix struct {
|
||||
*windows.RawSockaddrAny
|
||||
PrefixLength byte
|
||||
}
|
||||
|
||||
type RouteProtocol uint32 // MIB_IPFORWARD_PROTO
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_ipforward_row2
|
||||
type mib_row2 struct {
|
||||
luid NetLUID
|
||||
index uint32
|
||||
destinationPrefix *AddressPrefix
|
||||
nextHop *windows.RawSockaddrAny
|
||||
prefixLength byte
|
||||
lifetime uint32
|
||||
preferredLifetime uint32
|
||||
metric uint32
|
||||
protocol RouteProtocol
|
||||
loopback byte
|
||||
autoconfigured byte
|
||||
publish byte
|
||||
immortal byte
|
||||
age uint32
|
||||
origin byte
|
||||
}
|
||||
|
||||
func callBestRoute(source, dest net.IP) (*mib_row2, net.IP, error) {
|
||||
sourceAddr, _, _ := sockaddrToAny(ipAndZoneToSockaddr(source, ""))
|
||||
destAddr, _, _ := sockaddrToAny(ipAndZoneToSockaddr(dest, ""))
|
||||
bestRoute := make([]byte, 512)
|
||||
bestSource := make([]byte, 116)
|
||||
|
||||
err := getBestRoute2(nil, 0, sourceAddr, destAddr, 0, bestRoute, bestSource)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// interpret best route and best source.
|
||||
route, err := parseRoute(bestRoute)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// per https://docs.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_ipforward_row2
|
||||
// If the route is to a local loopback address or an IP address on the local link, the next hop is unspecified (all zeros)
|
||||
if isZero(route.nextHop) {
|
||||
route.nextHop = nil
|
||||
}
|
||||
|
||||
var bestSourceRaw windows.RawSockaddrAny
|
||||
bestSourceRaw.Addr.Family = binary.LittleEndian.Uint16(bestSource[0:2])
|
||||
copyInto(bestSourceRaw.Addr.Data[:], bestSource[2:16])
|
||||
copyInto(bestSourceRaw.Pad[:], bestSource[16:])
|
||||
addr, _ := bestSourceRaw.Sockaddr()
|
||||
bestSrc, _ := sockaddrToIPAndZone(addr)
|
||||
|
||||
return route, bestSrc, nil
|
||||
}
|
||||
|
||||
func copyInto(dst []int8, src []byte) {
|
||||
for i, b := range src {
|
||||
dst[i] = int8(b)
|
||||
}
|
||||
}
|
||||
|
||||
func isZero(addr *windows.RawSockaddrAny) bool {
|
||||
for _, b := range addr.Addr.Data {
|
||||
if b != 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for _, b := range addr.Pad {
|
||||
if b != 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func parseRoute(mib []byte) (*mib_row2, error) {
|
||||
var route mib_row2
|
||||
var err error
|
||||
|
||||
route.luid = NetLUID(binary.LittleEndian.Uint64(mib[0:]))
|
||||
route.index = binary.LittleEndian.Uint32(mib[8:])
|
||||
idx := 0
|
||||
route.destinationPrefix, idx, err = readDestPrefix(mib, 12)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
route.nextHop, idx, err = readSockAddr(mib, idx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
route.prefixLength = mib[idx]
|
||||
idx += 1
|
||||
route.lifetime = binary.LittleEndian.Uint32(mib[idx : idx+4])
|
||||
idx += 4
|
||||
route.preferredLifetime = binary.LittleEndian.Uint32(mib[idx : idx+4])
|
||||
idx += 4
|
||||
route.metric = binary.LittleEndian.Uint32(mib[idx : idx+4])
|
||||
idx += 4
|
||||
route.protocol = RouteProtocol(binary.LittleEndian.Uint32(mib[idx : idx+4]))
|
||||
idx += 4
|
||||
route.loopback = mib[idx]
|
||||
idx += 1
|
||||
route.autoconfigured = mib[idx]
|
||||
idx += 1
|
||||
route.publish = mib[idx]
|
||||
idx += 1
|
||||
route.immortal = mib[idx]
|
||||
idx += 1
|
||||
route.age = binary.LittleEndian.Uint32(mib[idx : idx+4])
|
||||
idx += 4
|
||||
route.origin = mib[idx]
|
||||
|
||||
return &route, err
|
||||
}
|
||||
|
||||
func readDestPrefix(buffer []byte, idx int) (*AddressPrefix, int, error) {
|
||||
sock, idx2, err := readSockAddr(buffer, idx)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
pfixLen := buffer[idx2]
|
||||
if idx2-idx > 32 {
|
||||
return nil, idx, fmt.Errorf("Unexpectedly large internal sockaddr struct")
|
||||
}
|
||||
return &AddressPrefix{sock, pfixLen}, idx + 32, nil
|
||||
}
|
||||
|
||||
func readSockAddr(buffer []byte, idx int) (*windows.RawSockaddrAny, int, error) {
|
||||
var rsa windows.RawSockaddrAny
|
||||
rsa.Addr.Family = binary.LittleEndian.Uint16(buffer[idx : idx+2])
|
||||
if rsa.Addr.Family == windows.AF_INET || rsa.Addr.Family == windows.AF_UNSPEC {
|
||||
copyInto(rsa.Addr.Data[:], buffer[idx+2:idx+16])
|
||||
return &rsa, idx + 16, nil
|
||||
} else if rsa.Addr.Family == windows.AF_INET6 {
|
||||
copyInto(rsa.Addr.Data[:], buffer[idx+2:idx+16])
|
||||
copyInto(rsa.Pad[:], buffer[idx+16:idx+28])
|
||||
return &rsa, idx + 28, nil
|
||||
} else {
|
||||
return nil, 0, fmt.Errorf("Unknown windows addr family %d", rsa.Addr.Family)
|
||||
}
|
||||
}
|
||||
|
||||
func getBestRoute2(interfaceLuid *NetLUID, interfaceIndex uint32, sourceAddress, destinationAddress *windows.RawSockaddrAny, addressSortOptions uint32, bestRoute []byte, bestSourceAddress []byte) (errcode error) {
|
||||
r0, _, _ := procGetBestRoute2.Call(
|
||||
uintptr(unsafe.Pointer(interfaceLuid)),
|
||||
uintptr(interfaceIndex),
|
||||
uintptr(unsafe.Pointer(sourceAddress)),
|
||||
uintptr(unsafe.Pointer(destinationAddress)),
|
||||
uintptr(addressSortOptions),
|
||||
uintptr(unsafe.Pointer(&bestRoute[0])),
|
||||
uintptr(unsafe.Pointer(&bestSourceAddress[0])))
|
||||
if r0 != 0 {
|
||||
errcode = windows.Errno(r0)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getIface(index uint32) *net.Interface {
|
||||
var ifRow windows.MibIfRow
|
||||
ifRow.Index = index
|
||||
err := windows.GetIfEntry(&ifRow)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
physAddrLen := int(ifRow.PhysAddrLen)
|
||||
if len(ifRow.PhysAddr) < physAddrLen && physAddrLen >= 0 {
|
||||
physAddrLen = len(ifRow.PhysAddr)
|
||||
}
|
||||
physAddr := ifRow.PhysAddr[:physAddrLen]
|
||||
|
||||
ifaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
for _, iface := range ifaces {
|
||||
if bytes.Equal(iface.HardwareAddr, physAddr) {
|
||||
return &iface
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type winRouter struct{}
|
||||
|
||||
func (r *winRouter) Route(dst net.IP) (iface *net.Interface, gateway, preferredSrc net.IP, err error) {
|
||||
return r.RouteWithSrc(nil, nil, dst)
|
||||
}
|
||||
|
||||
func (r *winRouter) RouteWithSrc(input net.HardwareAddr, src, dst net.IP) (iface *net.Interface, gateway, preferredSrc net.IP, err error) {
|
||||
route, pref, err := callBestRoute(src, dst)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
iface = getIface(route.index)
|
||||
|
||||
if route.nextHop == nil || route.nextHop.Addr.Family == 0 /* AF_UNDEF */ {
|
||||
return iface, nil, pref, nil
|
||||
}
|
||||
addr, err := route.nextHop.Sockaddr()
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
nextHop, _ := sockaddrToIPAndZone(addr)
|
||||
|
||||
return iface, nextHop, pref, nil
|
||||
}
|
||||
|
||||
func New() (routing.Router, error) {
|
||||
rtr := &winRouter{}
|
||||
return rtr, nil
|
||||
}
|
130
vendor/github.com/libp2p/go-netroute/sockaddr_windows.go
generated
vendored
Normal file
130
vendor/github.com/libp2p/go-netroute/sockaddr_windows.go
generated
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
//go:build windows
|
||||
|
||||
package netroute
|
||||
|
||||
import (
|
||||
"net"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// socklen is a type for the length of a sockaddr.
|
||||
type socklen uint
|
||||
|
||||
// ipAndZoneToSockaddr converts a net.IP (with optional IPv6 Zone) to a Sockaddr
|
||||
// Returns nil if conversion fails.
|
||||
func ipAndZoneToSockaddr(ip net.IP, zone string) windows.Sockaddr {
|
||||
// Unspecified?
|
||||
if ip == nil {
|
||||
if zone != "" {
|
||||
return &windows.SockaddrInet6{ZoneId: uint32(ip6ZoneToInt(zone))}
|
||||
}
|
||||
return new(windows.SockaddrInet4)
|
||||
}
|
||||
|
||||
// Valid IPv4?
|
||||
if ip4 := ip.To4(); ip4 != nil && zone == "" {
|
||||
var buf [4]byte
|
||||
copy(buf[:], ip4) // last 4 bytes
|
||||
return &windows.SockaddrInet4{Addr: buf}
|
||||
}
|
||||
|
||||
// Valid IPv6 address?
|
||||
if ip6 := ip.To16(); ip6 != nil {
|
||||
var buf [16]byte
|
||||
copy(buf[:], ip6)
|
||||
return &windows.SockaddrInet6{Addr: buf, ZoneId: uint32(ip6ZoneToInt(zone))}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// sockaddrToIPAndZone converts a Sockaddr to a net.IP (with optional IPv6 Zone)
|
||||
// Returns nil if conversion fails.
|
||||
func sockaddrToIPAndZone(sa windows.Sockaddr) (net.IP, string) {
|
||||
switch sa := sa.(type) {
|
||||
case *windows.SockaddrInet4:
|
||||
ip := make([]byte, 16)
|
||||
// V4InV6Prefix
|
||||
ip[10] = 0xff
|
||||
ip[11] = 0xff
|
||||
copy(ip[12:16], sa.Addr[:])
|
||||
return ip, ""
|
||||
case *windows.SockaddrInet6:
|
||||
ip := make([]byte, 16)
|
||||
copy(ip, sa.Addr[:])
|
||||
return ip, ip6ZoneToString(int(sa.ZoneId))
|
||||
}
|
||||
return nil, ""
|
||||
}
|
||||
|
||||
func sockaddrToAny(sa windows.Sockaddr) (*windows.RawSockaddrAny, socklen, error) {
|
||||
if sa == nil {
|
||||
return nil, 0, syscall.EINVAL
|
||||
}
|
||||
|
||||
switch sa := sa.(type) {
|
||||
case *windows.SockaddrInet4:
|
||||
if sa.Port < 0 || sa.Port > 0xFFFF {
|
||||
return nil, 0, syscall.EINVAL
|
||||
}
|
||||
raw := new(windows.RawSockaddrAny)
|
||||
raw.Addr.Family = windows.AF_INET
|
||||
raw4 := (*windows.RawSockaddrInet4)(unsafe.Pointer(raw))
|
||||
p := (*[2]byte)(unsafe.Pointer(&raw4.Port))
|
||||
p[0] = byte(sa.Port >> 8)
|
||||
p[1] = byte(sa.Port)
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
raw4.Addr[i] = sa.Addr[i]
|
||||
}
|
||||
return raw, socklen(unsafe.Sizeof(*raw4)), nil
|
||||
case *windows.SockaddrInet6:
|
||||
if sa.Port < 0 || sa.Port > 0xFFFF {
|
||||
return nil, 0, syscall.EINVAL
|
||||
}
|
||||
raw := new(windows.RawSockaddrAny)
|
||||
raw.Addr.Family = windows.AF_INET6
|
||||
raw6 := (*windows.RawSockaddrInet6)(unsafe.Pointer(raw))
|
||||
p := (*[2]byte)(unsafe.Pointer(&raw6.Port))
|
||||
p[0] = byte(sa.Port >> 8)
|
||||
p[1] = byte(sa.Port)
|
||||
raw6.Scope_id = sa.ZoneId
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
raw6.Addr[i] = sa.Addr[i]
|
||||
}
|
||||
return raw, socklen(unsafe.Sizeof(*raw6)), nil
|
||||
case *windows.SockaddrUnix:
|
||||
return nil, 0, syscall.EWINDOWS
|
||||
}
|
||||
return nil, 0, syscall.EAFNOSUPPORT
|
||||
}
|
||||
|
||||
// from: go/src/pkg/net/ipsock.go
|
||||
|
||||
// ip6ZoneToString converts an IP6 Zone unix int to a net string
|
||||
// returns "" if zone is 0
|
||||
func ip6ZoneToString(zone int) string {
|
||||
if zone == 0 {
|
||||
return ""
|
||||
}
|
||||
if ifi, err := net.InterfaceByIndex(zone); err == nil {
|
||||
return ifi.Name
|
||||
}
|
||||
return strconv.Itoa(zone)
|
||||
}
|
||||
|
||||
// ip6ZoneToInt converts an IP6 Zone net string to a unix int
|
||||
// returns 0 if zone is ""
|
||||
func ip6ZoneToInt(zone string) int {
|
||||
if zone == "" {
|
||||
return 0
|
||||
}
|
||||
if ifi, err := net.InterfaceByName(zone); err == nil {
|
||||
return ifi.Index
|
||||
}
|
||||
n, _ := strconv.ParseInt(zone, 10, 32)
|
||||
return int(n)
|
||||
}
|
3
vendor/github.com/libp2p/go-netroute/version.json
generated
vendored
Normal file
3
vendor/github.com/libp2p/go-netroute/version.json
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"version": "v0.2.1"
|
||||
}
|
Reference in New Issue
Block a user