215 lines
3.9 KiB
Go
215 lines
3.9 KiB
Go
package host
|
|
|
|
import (
|
|
"fmt"
|
|
"lux/proto"
|
|
"net"
|
|
"net/netip"
|
|
"strings"
|
|
)
|
|
|
|
// Option containing all network interfaces of host (excluding loopbacks)
|
|
|
|
// IPv6 GUA
|
|
// IPv6 ULA
|
|
// IPv6 LL
|
|
// IPv4
|
|
|
|
type LuxNetAddrType int
|
|
|
|
const (
|
|
LuxNetAddrType4 = 0
|
|
LuxNetAddrType6LL = 1
|
|
LuxNetAddrType6ULA = 2
|
|
LuxNetAddrType6GUA = 3
|
|
)
|
|
|
|
type LuxNetAddr struct {
|
|
Type LuxNetAddrType
|
|
Addr netip.Addr
|
|
}
|
|
|
|
func (addr *LuxNetAddr) Read(rd *proto.LuxBuffer) error {
|
|
addrType, err := rd.ReadUint16()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
addr.Type = LuxNetAddrType(addrType)
|
|
|
|
ipAddr, err := rd.ReadIP()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
addr.Addr = ipAddr
|
|
|
|
return nil
|
|
}
|
|
|
|
func (addr *LuxNetAddr) Write(wd *proto.LuxBuffer) {
|
|
wd.WriteUint16(uint16(addr.Type))
|
|
wd.WriteIP(addr.Addr)
|
|
}
|
|
|
|
type LuxNetInterface struct {
|
|
Name string
|
|
Index int
|
|
Addrs []LuxNetAddr
|
|
}
|
|
|
|
func NewLuxNetInterface() LuxNetInterface {
|
|
return LuxNetInterface{
|
|
Addrs: make([]LuxNetAddr, 0),
|
|
}
|
|
}
|
|
|
|
func parseNetlinkIp(addr string) string {
|
|
if strings.ContainsRune(addr, '/') {
|
|
return strings.Split(addr, "/")[0]
|
|
}
|
|
|
|
return addr
|
|
}
|
|
|
|
func (luxNet *LuxNetInterface) FromNetlink(netif *net.Interface) error {
|
|
luxNet.Name = netif.Name
|
|
luxNet.Index = netif.Index
|
|
|
|
// enumerate interface ips
|
|
addrs, err := netif.Addrs()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, addr := range addrs {
|
|
ip := net.ParseIP(parseNetlinkIp(addr.String()))
|
|
if ip == nil {
|
|
return err
|
|
}
|
|
|
|
luxAddr := LuxNetAddr{}
|
|
if ip.IsLoopback() {
|
|
continue // loopbacks are useless to LUX
|
|
} else if ip.To4() == nil {
|
|
// got IPv6
|
|
if ip.IsLinkLocalUnicast() {
|
|
luxAddr.Type = LuxNetAddrType6LL
|
|
} else if ip[0] == 0xFD || ip[0] == 0xFC {
|
|
// ULA - fc00::/7 with L = 1 -> fd00::/8,
|
|
// tho fc L 0 is not defined we still gonna assume its ULA
|
|
luxAddr.Type = LuxNetAddrType6ULA
|
|
} else {
|
|
// anything else is global unicast
|
|
luxAddr.Type = LuxNetAddrType6GUA
|
|
}
|
|
} else {
|
|
// got IPv4
|
|
luxAddr.Type = LuxNetAddrType4
|
|
}
|
|
|
|
luxAddr.Addr = proto.LuxProtoIPToAddr(ip)
|
|
|
|
luxNet.Addrs = append(luxNet.Addrs, luxAddr)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (netif *LuxNetInterface) Read(rd *proto.LuxBuffer) error {
|
|
name, err := rd.ReadString()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
netif.Name = name
|
|
|
|
idx, err := rd.ReadUint16()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
netif.Index = int(idx)
|
|
|
|
addrNum, err := rd.ReadUint16()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for i := 0; i < int(addrNum); i++ {
|
|
addr := LuxNetAddr{}
|
|
if addr.Read(rd) != nil {
|
|
return err
|
|
}
|
|
|
|
netif.Addrs = append(netif.Addrs, addr)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (netif *LuxNetInterface) Write(wd *proto.LuxBuffer) {
|
|
wd.WriteString(netif.Name)
|
|
wd.WriteUint16(uint16(netif.Index))
|
|
|
|
wd.WriteUint16(uint16(len(netif.Addrs)))
|
|
for _, addr := range netif.Addrs {
|
|
addr.Write(wd)
|
|
}
|
|
}
|
|
|
|
type LuxOptionNetIf struct {
|
|
Interfaces map[string]*LuxNetInterface
|
|
}
|
|
|
|
func NewLuxOptionNetIf() LuxOptionNetIf {
|
|
return LuxOptionNetIf{
|
|
Interfaces: make(map[string]*LuxNetInterface),
|
|
}
|
|
}
|
|
|
|
func (opt *LuxOptionNetIf) EnumerateNetlink() error {
|
|
ifaces, err := net.Interfaces()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, iface := range ifaces {
|
|
netif := NewLuxNetInterface()
|
|
if err := netif.FromNetlink(&iface); err != nil {
|
|
return nil
|
|
}
|
|
|
|
if len(netif.Addrs) > 0 {
|
|
// only add if we got atleast 1 ip, since we might want to skip
|
|
// netif loopback that has no IP because we skip one in FromNetlink
|
|
fmt.Println(netif)
|
|
opt.Interfaces[netif.Name] = &netif
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (opt *LuxOptionNetIf) Read(rd *proto.LuxBuffer) error {
|
|
ifNum, err := rd.ReadUint16()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for i := 0; i < int(ifNum); i++ {
|
|
netif := NewLuxNetInterface()
|
|
if err := netif.Read(rd); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (opt *LuxOptionNetIf) Write(wd *proto.LuxBuffer) {
|
|
wd.WriteUint16(uint16(len(opt.Interfaces)))
|
|
for _, netif := range opt.Interfaces {
|
|
netif.Write(wd)
|
|
}
|
|
}
|
|
|
|
func (*LuxOptionNetIf) Type() LuxOptionType {
|
|
return LuxOptionTypeNetIf
|
|
}
|