ZeroTierOne/go/pkg/zerotier/endpoint.go

115 lines
2.2 KiB
Go

package zerotier
import (
"encoding/binary"
"errors"
)
// Endpoint types are the same as the enum values in Endpoint.hpp in the core.
const (
EndpointTypeNil = 0
EndpointTypeInetAddr = 1
EndpointTypeDnsName = 2
EndpointTypeZeroTier = 3
EndpointTypeUrl = 4
EndpointTypeEthernet = 5
EndpointTypeUnrecognized = 255
)
type Endpoint struct {
Type int
value, value2 interface{}
}
var (
ErrInvalidEndpoint = errors.New("invalid marshaled endpoint object")
)
func (ep *Endpoint) unmarshalZT(b []byte) (int, error) {
if len(b) == 0 {
return 0, ErrInvalidEndpoint
}
switch b[0] {
case EndpointTypeNil:
*ep = Endpoint{Type: EndpointTypeNil}
return 1, nil
case EndpointTypeInetAddr:
ina := new(InetAddress)
inlen, err := ina.unmarshalZT(b[1:])
if err != nil {
return 0, err
}
*ep = Endpoint{
Type: EndpointTypeInetAddr,
value: ina,
}
return 1 + inlen, nil
case EndpointTypeDnsName:
zeroAt := 1
for i := 1; i < len(b); i++ {
if b[i] == 0 {
zeroAt = i
break
}
}
if zeroAt == 1 || (1 + zeroAt + 3) > len(b) {
return 0, ErrInvalidEndpoint
}
port := binary.BigEndian.Uint16(b[zeroAt+1:zeroAt+3])
*ep = Endpoint{
Type: EndpointTypeDnsName,
value: string(b[1:zeroAt]),
value2: &port,
}
return zeroAt + 3, nil
case EndpointTypeZeroTier:
if len(b) != 54 {
return 0, ErrInvalidEndpoint
}
a, err := NewAddressFromBytes(b[1:6])
if err != nil {
return 0, err
}
*ep = Endpoint{
Type: EndpointTypeZeroTier,
value: a,
value2: append(make([]byte, 0, 48), b[6:54]...),
}
return 54, nil
case EndpointTypeUrl:
zeroAt := 1
for i := 1; i < len(b); i++ {
if b[i] == 0 {
zeroAt = i
break
}
}
if zeroAt == 1 {
return 0, ErrInvalidEndpoint
}
*ep = Endpoint{
Type: EndpointTypeUrl,
value: string(b[1:zeroAt]),
}
return zeroAt + 2, nil
case EndpointTypeEthernet:
if len(b) != 7 {
return 0, ErrInvalidEndpoint
}
m, err := NewMACFromBytes(b[1:7])
if err != nil {
return 0, err
}
*ep = Endpoint{
Type: EndpointTypeEthernet,
value: m,
}
return 7, nil
default:
if len(b) < 2 {
return 0, ErrInvalidEndpoint
}
*ep = Endpoint{Type: EndpointTypeUnrecognized}
return 1 + int(b[1]), nil
}
}