mirror of
https://github.com/netbirdio/netbird.git
synced 2024-11-23 08:33:45 +01:00
138 lines
3.3 KiB
Go
138 lines
3.3 KiB
Go
|
// Package stdnet is an extension of the pion's stdnet.
|
||
|
// With it the list of the interface can come from external source.
|
||
|
// More info: https://github.com/golang/go/issues/40569
|
||
|
package stdnet
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"net"
|
||
|
"strings"
|
||
|
|
||
|
"github.com/pion/transport/v2"
|
||
|
"github.com/pion/transport/v2/stdnet"
|
||
|
log "github.com/sirupsen/logrus"
|
||
|
)
|
||
|
|
||
|
// Net is an implementation of the net.Net interface
|
||
|
// based on functions of the standard net package.
|
||
|
type Net struct {
|
||
|
stdnet.Net
|
||
|
interfaces []*transport.Interface
|
||
|
}
|
||
|
|
||
|
// NewNet creates a new StdNet instance.
|
||
|
func NewNet(iFaceDiscover IFaceDiscover) (*Net, error) {
|
||
|
n := &Net{}
|
||
|
|
||
|
return n, n.UpdateInterfaces(iFaceDiscover)
|
||
|
}
|
||
|
|
||
|
// UpdateInterfaces updates the internal list of network interfaces
|
||
|
// and associated addresses.
|
||
|
func (n *Net) UpdateInterfaces(iFaceDiscover IFaceDiscover) error {
|
||
|
ifacesString, err := iFaceDiscover.IFaces()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
n.interfaces = parseInterfacesString(ifacesString)
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
// Interfaces returns a slice of interfaces which are available on the
|
||
|
// system
|
||
|
func (n *Net) Interfaces() ([]*transport.Interface, error) {
|
||
|
return n.interfaces, nil
|
||
|
}
|
||
|
|
||
|
// InterfaceByIndex returns the interface specified by index.
|
||
|
//
|
||
|
// On Solaris, it returns one of the logical network interfaces
|
||
|
// sharing the logical data link; for more precision use
|
||
|
// InterfaceByName.
|
||
|
func (n *Net) InterfaceByIndex(index int) (*transport.Interface, error) {
|
||
|
for _, ifc := range n.interfaces {
|
||
|
if ifc.Index == index {
|
||
|
return ifc, nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nil, fmt.Errorf("%w: index=%d", transport.ErrInterfaceNotFound, index)
|
||
|
}
|
||
|
|
||
|
// InterfaceByName returns the interface specified by name.
|
||
|
func (n *Net) InterfaceByName(name string) (*transport.Interface, error) {
|
||
|
for _, ifc := range n.interfaces {
|
||
|
if ifc.Name == name {
|
||
|
return ifc, nil
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nil, fmt.Errorf("%w: %s", transport.ErrInterfaceNotFound, name)
|
||
|
}
|
||
|
|
||
|
func parseInterfacesString(interfaces string) []*transport.Interface {
|
||
|
ifs := []*transport.Interface{}
|
||
|
|
||
|
for _, iface := range strings.Split(interfaces, "\n") {
|
||
|
if strings.TrimSpace(iface) == "" {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
fields := strings.Split(iface, "|")
|
||
|
if len(fields) != 2 {
|
||
|
log.Warnf("parseInterfacesString: unable to split %q", iface)
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
var name string
|
||
|
var index, mtu int
|
||
|
var up, broadcast, loopback, pointToPoint, multicast bool
|
||
|
_, err := fmt.Sscanf(fields[0], "%s %d %d %t %t %t %t %t",
|
||
|
&name, &index, &mtu, &up, &broadcast, &loopback, &pointToPoint, &multicast)
|
||
|
if err != nil {
|
||
|
log.Warnf("parseInterfacesString: unable to parse %q: %v", iface, err)
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
newIf := net.Interface{
|
||
|
Name: name,
|
||
|
Index: index,
|
||
|
MTU: mtu,
|
||
|
}
|
||
|
if up {
|
||
|
newIf.Flags |= net.FlagUp
|
||
|
}
|
||
|
if broadcast {
|
||
|
newIf.Flags |= net.FlagBroadcast
|
||
|
}
|
||
|
if loopback {
|
||
|
newIf.Flags |= net.FlagLoopback
|
||
|
}
|
||
|
if pointToPoint {
|
||
|
newIf.Flags |= net.FlagPointToPoint
|
||
|
}
|
||
|
if multicast {
|
||
|
newIf.Flags |= net.FlagMulticast
|
||
|
}
|
||
|
|
||
|
ifc := transport.NewInterface(newIf)
|
||
|
|
||
|
addrs := strings.Trim(fields[1], " \n")
|
||
|
foundAddress := false
|
||
|
for _, addr := range strings.Split(addrs, " ") {
|
||
|
ip, ipNet, err := net.ParseCIDR(addr)
|
||
|
if err != nil {
|
||
|
log.Warnf("%s", err)
|
||
|
continue
|
||
|
}
|
||
|
ipNet.IP = ip
|
||
|
ifc.AddAddress(ipNet)
|
||
|
foundAddress = true
|
||
|
}
|
||
|
if foundAddress {
|
||
|
ifs = append(ifs, ifc)
|
||
|
}
|
||
|
}
|
||
|
return ifs
|
||
|
}
|