mirror of
https://github.com/danderson/netboot.git
synced 2025-10-17 02:21:20 +02:00
fixing coding-style related issues
This commit is contained in:
parent
11a8e61c10
commit
8725ede99b
@ -6,13 +6,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type IdentityAssociation struct {
|
type IdentityAssociation struct {
|
||||||
IpAddress net.IP
|
IPAddress net.IP
|
||||||
ClientId []byte
|
ClientID []byte
|
||||||
InterfaceId []byte
|
InterfaceID []byte
|
||||||
CreatedAt time.Time
|
CreatedAt time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
type AddressPool interface {
|
type AddressPool interface {
|
||||||
ReserveAddresses(clientId []byte, interfaceIds [][]byte) ([]*IdentityAssociation, error)
|
ReserveAddresses(clientID []byte, interfaceIds [][]byte) ([]*IdentityAssociation, error)
|
||||||
ReleaseAddresses(clientId []byte, interfaceIds [][]byte)
|
ReleaseAddresses(clientID []byte, interfaceIds [][]byte)
|
||||||
}
|
}
|
||||||
|
@ -11,75 +11,75 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type BootConfiguration interface {
|
type BootConfiguration interface {
|
||||||
GetBootUrl(id []byte, clientArchType uint16) ([]byte, error)
|
GetBootURL(id []byte, clientArchType uint16) ([]byte, error)
|
||||||
GetPreference() []byte
|
GetPreference() []byte
|
||||||
GetRecursiveDns() []net.IP
|
GetRecursiveDNS() []net.IP
|
||||||
}
|
}
|
||||||
|
|
||||||
type StaticBootConfiguration struct {
|
type StaticBootConfiguration struct {
|
||||||
HttpBootUrl []byte
|
HTTPBootURL []byte
|
||||||
IPxeBootUrl []byte
|
IPxeBootURL []byte
|
||||||
RecursiveDns []net.IP
|
RecursiveDNS []net.IP
|
||||||
Preference []byte
|
Preference []byte
|
||||||
UsePreference bool
|
UsePreference bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeStaticBootConfiguration(httpBootUrl, ipxeBootUrl string, preference uint8, usePreference bool,
|
func MakeStaticBootConfiguration(httpBootURL, ipxeBootURL string, preference uint8, usePreference bool,
|
||||||
dnsServerAddresses []net.IP) *StaticBootConfiguration {
|
dnsServerAddresses []net.IP) *StaticBootConfiguration {
|
||||||
ret := &StaticBootConfiguration{HttpBootUrl: []byte(httpBootUrl), IPxeBootUrl: []byte(ipxeBootUrl), UsePreference: usePreference}
|
ret := &StaticBootConfiguration{HTTPBootURL: []byte(httpBootURL), IPxeBootURL: []byte(ipxeBootURL), UsePreference: usePreference}
|
||||||
if usePreference {
|
if usePreference {
|
||||||
ret.Preference = make([]byte, 1)
|
ret.Preference = make([]byte, 1)
|
||||||
ret.Preference[0] = byte(preference)
|
ret.Preference[0] = byte(preference)
|
||||||
}
|
}
|
||||||
ret.RecursiveDns = dnsServerAddresses
|
ret.RecursiveDNS = dnsServerAddresses
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bc *StaticBootConfiguration) GetBootUrl(id []byte, clientArchType uint16) ([]byte, error) {
|
func (bc *StaticBootConfiguration) GetBootURL(id []byte, clientArchType uint16) ([]byte, error) {
|
||||||
if 0x10 == clientArchType {
|
if 0x10 == clientArchType {
|
||||||
return bc.HttpBootUrl, nil
|
return bc.HTTPBootURL, nil
|
||||||
}
|
}
|
||||||
return bc.IPxeBootUrl, nil
|
return bc.IPxeBootURL, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bc *StaticBootConfiguration) GetPreference() []byte {
|
func (bc *StaticBootConfiguration) GetPreference() []byte {
|
||||||
return bc.Preference
|
return bc.Preference
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bc *StaticBootConfiguration) GetRecursiveDns() []net.IP {
|
func (bc *StaticBootConfiguration) GetRecursiveDNS() []net.IP {
|
||||||
return bc.RecursiveDns
|
return bc.RecursiveDNS
|
||||||
}
|
}
|
||||||
|
|
||||||
type ApiBootConfiguration struct {
|
type APIBootConfiguration struct {
|
||||||
client *http.Client
|
Client *http.Client
|
||||||
urlPrefix string
|
URLPrefix string
|
||||||
RecursiveDns []net.IP
|
RecursiveDNS []net.IP
|
||||||
Preference []byte
|
Preference []byte
|
||||||
UsePreference bool
|
UsePreference bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeApiBootConfiguration(url string, timeout time.Duration, preference uint8, usePreference bool,
|
func MakeApiBootConfiguration(url string, timeout time.Duration, preference uint8, usePreference bool,
|
||||||
dnsServerAddresses []net.IP) *ApiBootConfiguration {
|
dnsServerAddresses []net.IP) *APIBootConfiguration {
|
||||||
if !strings.HasSuffix(url, "/") {
|
if !strings.HasSuffix(url, "/") {
|
||||||
url += "/"
|
url += "/"
|
||||||
}
|
}
|
||||||
ret := &ApiBootConfiguration{
|
ret := &APIBootConfiguration{
|
||||||
client: &http.Client{Timeout: timeout},
|
Client: &http.Client{Timeout: timeout},
|
||||||
urlPrefix: url + "v1",
|
URLPrefix: url + "v1",
|
||||||
UsePreference: usePreference,
|
UsePreference: usePreference,
|
||||||
}
|
}
|
||||||
if usePreference {
|
if usePreference {
|
||||||
ret.Preference = make([]byte, 1)
|
ret.Preference = make([]byte, 1)
|
||||||
ret.Preference[0] = byte(preference)
|
ret.Preference[0] = byte(preference)
|
||||||
}
|
}
|
||||||
ret.RecursiveDns = dnsServerAddresses
|
ret.RecursiveDNS = dnsServerAddresses
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bc *ApiBootConfiguration) GetBootUrl(id []byte, clientArchType uint16) ([]byte, error) {
|
func (bc *APIBootConfiguration) GetBootURL(id []byte, clientArchType uint16) ([]byte, error) {
|
||||||
reqURL := fmt.Sprintf("%s/boot/%x/%d", bc.urlPrefix, id, clientArchType)
|
reqURL := fmt.Sprintf("%s/boot/%x/%d", bc.URLPrefix, id, clientArchType)
|
||||||
resp, err := bc.client.Get(reqURL)
|
resp, err := bc.Client.Get(reqURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -96,13 +96,13 @@ func (bc *ApiBootConfiguration) GetBootUrl(id []byte, clientArchType uint16) ([]
|
|||||||
return []byte(url), nil
|
return []byte(url), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bc *ApiBootConfiguration) makeURLAbsolute(urlStr string) (string, error) {
|
func (bc *APIBootConfiguration) makeURLAbsolute(urlStr string) (string, error) {
|
||||||
u, err := url.Parse(urlStr)
|
u, err := url.Parse(urlStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("%q is not an URL", urlStr)
|
return "", fmt.Errorf("%q is not an URL", urlStr)
|
||||||
}
|
}
|
||||||
if !u.IsAbs() {
|
if !u.IsAbs() {
|
||||||
base, err := url.Parse(bc.urlPrefix)
|
base, err := url.Parse(bc.URLPrefix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -111,10 +111,10 @@ func (bc *ApiBootConfiguration) makeURLAbsolute(urlStr string) (string, error) {
|
|||||||
return u.String(), nil
|
return u.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bc *ApiBootConfiguration) GetPreference() []byte {
|
func (bc *APIBootConfiguration) GetPreference() []byte {
|
||||||
return bc.Preference
|
return bc.Preference
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bc *ApiBootConfiguration) GetRecursiveDns() []net.IP {
|
func (bc *APIBootConfiguration) GetRecursiveDNS() []net.IP {
|
||||||
return bc.RecursiveDns
|
return bc.RecursiveDNS
|
||||||
}
|
}
|
||||||
|
112
dhcp6/options.go
112
dhcp6/options.go
@ -8,55 +8,55 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
OptClientId uint16 = 1 // IPMask
|
OptClientID uint16 = 1 // IPMask
|
||||||
OptServerId = 2 // int32
|
OptServerID = 2 // int32
|
||||||
OptIaNa = 3 // IPs
|
OptIaNa = 3 // IPs
|
||||||
OptIaTa = 4 // IPs
|
OptIaTa = 4 // IPs
|
||||||
OptIaAddr = 5 // string
|
OptIaAddr = 5 // string
|
||||||
OptOro = 6 // uint16
|
OptOro = 6 // uint16
|
||||||
OptPreference = 7 // string
|
OptPreference = 7 // string
|
||||||
OptElapsedTime = 8 // IP
|
OptElapsedTime = 8 // IP
|
||||||
OptRelayMessage = 9 // IP
|
OptRelayMessage = 9 // IP
|
||||||
OptAuth = 11 // []byte
|
OptAuth = 11 // []byte
|
||||||
OptUnicast = 12 // IP
|
OptUnicast = 12 // IP
|
||||||
OptStatusCode = 13 // uint32
|
OptStatusCode = 13 // uint32
|
||||||
OptRapidCommit = 14 // byte
|
OptRapidCommit = 14 // byte
|
||||||
OptUserClass = 15 // IP
|
OptUserClass = 15 // IP
|
||||||
OptVendorClass = 16 // []byte
|
OptVendorClass = 16 // []byte
|
||||||
OptVendorOpts = 17 // string
|
OptVendorOpts = 17 // string
|
||||||
OptInterfaceId = 18 // uint16
|
OptInterfaceID = 18 // uint16
|
||||||
OptReconfMsg = 19 // uint32
|
OptReconfMsg = 19 // uint32
|
||||||
OptReconfAccept = 20 // uint32
|
OptReconfAccept = 20 // uint32
|
||||||
OptRecursiveDns = 23 // []byte
|
OptRecursiveDNS = 23 // []byte
|
||||||
OptBootfileUrl = 59
|
OptBootfileURL = 59
|
||||||
OptBootfileParam = 60 //[][]byte
|
OptBootfileParam = 60 //[][]byte
|
||||||
OptClientArchType = 61 //[][]byte, sent by the client
|
OptClientArchType = 61 //[][]byte, sent by the Client
|
||||||
// 24? Domain search list
|
// 24? Domain search list
|
||||||
)
|
)
|
||||||
|
|
||||||
type Option struct {
|
type Option struct {
|
||||||
Id uint16
|
ID uint16
|
||||||
Length uint16
|
Length uint16
|
||||||
Value []byte
|
Value []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeOption(id uint16, value []byte) *Option {
|
func MakeOption(id uint16, value []byte) *Option {
|
||||||
return &Option{ Id: id, Length: uint16(len(value)), Value: value}
|
return &Option{ ID: id, Length: uint16(len(value)), Value: value}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Options map[uint16][]*Option
|
type Options map[uint16][]*Option
|
||||||
|
|
||||||
func MakeOptions(bs []byte) (Options, error) {
|
func MakeOptions(bs []byte) (Options, error) {
|
||||||
to_ret := make(Options)
|
ret := make(Options)
|
||||||
for len(bs) > 0 {
|
for len(bs) > 0 {
|
||||||
o, err := UnmarshalOption(bs)
|
o, err := UnmarshalOption(bs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
to_ret[o.Id] = append(to_ret[o.Id], &Option{ Id: o.Id, Length: o.Length, Value: bs[4 : 4+o.Length]})
|
ret[o.ID] = append(ret[o.ID], &Option{ ID: o.ID, Length: o.Length, Value: bs[4 : 4+o.Length]})
|
||||||
bs = bs[4+o.Length:]
|
bs = bs[4+o.Length:]
|
||||||
}
|
}
|
||||||
return to_ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func UnmarshalOption(bs []byte) (*Option, error) {
|
func UnmarshalOption(bs []byte) (*Option, error) {
|
||||||
@ -76,18 +76,18 @@ func UnmarshalOption(bs []byte) (*Option, error) {
|
|||||||
return nil, fmt.Errorf("option %d claims to have %d bytes of payload, but only has %d bytes", optionId, optionLength, len(bs[4:]))
|
return nil, fmt.Errorf("option %d claims to have %d bytes of payload, but only has %d bytes", optionId, optionLength, len(bs[4:]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &Option{ Id: optionId, Length: optionLength, Value: bs[4 : 4+optionLength]}, nil
|
return &Option{ ID: optionId, Length: optionLength, Value: bs[4 : 4+optionLength]}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o Options) HumanReadable() []string {
|
func (o Options) HumanReadable() []string {
|
||||||
to_ret := make([]string, 0, len(o))
|
to_ret := make([]string, 0, len(o))
|
||||||
for _, multipleOptions := range(o) {
|
for _, multipleOptions := range(o) {
|
||||||
for _, option := range(multipleOptions) {
|
for _, option := range(multipleOptions) {
|
||||||
switch option.Id {
|
switch option.ID {
|
||||||
case 3:
|
case 3:
|
||||||
to_ret = append(to_ret, o.HumanReadableIaNa(*option)...)
|
to_ret = append(to_ret, o.HumanReadableIaNa(*option)...)
|
||||||
default:
|
default:
|
||||||
to_ret = append(to_ret, fmt.Sprintf("Option: %d | %d | %d | %s\n", option.Id, option.Length, option.Value, option.Value))
|
to_ret = append(to_ret, fmt.Sprintf("Option: %d | %d | %d | %s\n", option.ID, option.Length, option.Value, option.Value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -127,10 +127,10 @@ func (o Options) HumanReadableIaNa(opt Option) []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o Options) AddOption(option *Option) {
|
func (o Options) AddOption(option *Option) {
|
||||||
_, present := o[option.Id]; if !present {
|
_, present := o[option.ID]; if !present {
|
||||||
o[option.Id] = make([]*Option, 0)
|
o[option.ID] = make([]*Option, 0)
|
||||||
}
|
}
|
||||||
o[option.Id] = append(o[option.Id], option)
|
o[option.ID] = append(o[option.ID], option)
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeIaNaOption(iaid []byte, t1, t2 uint32, iaOption *Option) *Option {
|
func MakeIaNaOption(iaid []byte, t1, t2 uint32, iaOption *Option) *Option {
|
||||||
@ -163,7 +163,7 @@ func MakeDNSServersOption(addresses []net.IP) *Option {
|
|||||||
for i, dnsAddress := range addresses {
|
for i, dnsAddress := range addresses {
|
||||||
copy(value[i*16:], dnsAddress)
|
copy(value[i*16:], dnsAddress)
|
||||||
}
|
}
|
||||||
return MakeOption(OptRecursiveDns, value)
|
return MakeOption(OptRecursiveDNS, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o Options) Marshal() ([]byte, error) {
|
func (o Options) Marshal() ([]byte, error) {
|
||||||
@ -185,7 +185,7 @@ func (o Options) Marshal() ([]byte, error) {
|
|||||||
func (o *Option) Marshal() ([]byte, error) {
|
func (o *Option) Marshal() ([]byte, error) {
|
||||||
buffer := bytes.NewBuffer(make([]byte, 0, o.Length + 2))
|
buffer := bytes.NewBuffer(make([]byte, 0, o.Length + 2))
|
||||||
|
|
||||||
err := binary.Write(buffer, binary.BigEndian, o.Id)
|
err := binary.Write(buffer, binary.BigEndian, o.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Error serializing option id: %s", err)
|
return nil, fmt.Errorf("Error serializing option id: %s", err)
|
||||||
}
|
}
|
||||||
@ -201,32 +201,32 @@ func (o *Option) Marshal() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o Options) UnmarshalOptionRequestOption() map[uint16]bool {
|
func (o Options) UnmarshalOptionRequestOption() map[uint16]bool {
|
||||||
to_ret := make(map[uint16]bool)
|
ret := make(map[uint16]bool)
|
||||||
|
|
||||||
_, present := o[OptOro]; if !present {
|
_, present := o[OptOro]; if !present {
|
||||||
return to_ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
oro_content := o[OptOro][0].Value
|
value := o[OptOro][0].Value
|
||||||
for i := 0; i < int(o[OptOro][0].Length)/2; i++ {
|
for i := 0; i < int(o[OptOro][0].Length)/2; i++ {
|
||||||
to_ret[uint16(binary.BigEndian.Uint16(oro_content[i*2:(i+1)*2]))] = true
|
ret[uint16(binary.BigEndian.Uint16(value[i*2:(i+1)*2]))] = true
|
||||||
}
|
}
|
||||||
return to_ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o Options) HasBootFileUrlOption() bool {
|
func (o Options) HasBootFileURLOption() bool {
|
||||||
requested_options := o.UnmarshalOptionRequestOption()
|
requestedOptions := o.UnmarshalOptionRequestOption()
|
||||||
_, present := requested_options[OptBootfileUrl]
|
_, present := requestedOptions[OptBootfileURL]
|
||||||
return present
|
return present
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o Options) HasClientId() bool {
|
func (o Options) HasClientID() bool {
|
||||||
_, present := o[OptClientId]
|
_, present := o[OptClientID]
|
||||||
return present
|
return present
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o Options) HasServerId() bool {
|
func (o Options) HasServerID() bool {
|
||||||
_, present := o[OptServerId]
|
_, present := o[OptServerID]
|
||||||
return present
|
return present
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,23 +245,23 @@ func (o Options) HasClientArchType() bool {
|
|||||||
return present
|
return present
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o Options) ClientId() []byte {
|
func (o Options) ClientID() []byte {
|
||||||
opt, exists := o[OptClientId]
|
opt, exists := o[OptClientID]
|
||||||
if exists {
|
if exists {
|
||||||
return opt[0].Value
|
return opt[0].Value
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o Options) ServerId() []byte {
|
func (o Options) ServerID() []byte {
|
||||||
opt, exists := o[OptServerId]
|
opt, exists := o[OptServerID]
|
||||||
if exists {
|
if exists {
|
||||||
return opt[0].Value
|
return opt[0].Value
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o Options) IaNaIds() [][]byte {
|
func (o Options) IaNaIDs() [][]byte {
|
||||||
options, exists := o[OptIaNa]
|
options, exists := o[OptIaNa]
|
||||||
ret := make([][]byte, 0)
|
ret := make([][]byte, 0)
|
||||||
if exists {
|
if exists {
|
||||||
@ -281,8 +281,8 @@ func (o Options) ClientArchType() uint16 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o Options) BootfileUrl() []byte {
|
func (o Options) BootFileURL() []byte {
|
||||||
opt, exists := o[OptBootfileUrl]
|
opt, exists := o[OptBootfileURL]
|
||||||
if exists {
|
if exists {
|
||||||
return opt[0].Value
|
return opt[0].Value
|
||||||
}
|
}
|
||||||
|
@ -7,39 +7,39 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestMarshalOption(t *testing.T) {
|
func TestMarshalOption(t *testing.T) {
|
||||||
expectedUrl := []byte("http://blah")
|
expectedURL := []byte("http://blah")
|
||||||
expectedLength := uint16(len(expectedUrl))
|
expectedLength := uint16(len(expectedURL))
|
||||||
opt := &Option{Id: OptBootfileUrl, Length: expectedLength, Value: expectedUrl}
|
opt := &Option{ID: OptBootfileURL, Length: expectedLength, Value: expectedURL}
|
||||||
|
|
||||||
marshalled, err := opt.Marshal()
|
marshalled, err := opt.Marshal()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected marshalling failure.")
|
t.Fatalf("Unexpected marshalling failure.")
|
||||||
}
|
}
|
||||||
|
|
||||||
if id := uint16(binary.BigEndian.Uint16(marshalled[0:2])); id != OptBootfileUrl {
|
if id := uint16(binary.BigEndian.Uint16(marshalled[0:2])); id != OptBootfileURL {
|
||||||
t.Fatalf("Expected optionId %d, got: %d", OptBootfileUrl, id)
|
t.Fatalf("Expected optionId %d, got: %d", OptBootfileURL, id)
|
||||||
}
|
}
|
||||||
if l := uint16(binary.BigEndian.Uint16(marshalled[2:4])); l != expectedLength {
|
if l := uint16(binary.BigEndian.Uint16(marshalled[2:4])); l != expectedLength {
|
||||||
t.Fatalf("Expected length of %d, got: %d", expectedLength, l)
|
t.Fatalf("Expected length of %d, got: %d", expectedLength, l)
|
||||||
}
|
}
|
||||||
if url := marshalled[4:]; string(url) != string(expectedUrl) {
|
if url := marshalled[4:]; string(url) != string(expectedURL) {
|
||||||
t.Fatalf("Expected %s, got %s", expectedUrl, url)
|
t.Fatalf("Expected %s, got %s", expectedURL, url)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMakeIaAddrOption(t *testing.T) {
|
func TestMakeIaAddrOption(t *testing.T) {
|
||||||
expectedIp := net.ParseIP("2001:db8:f00f:cafe::99")
|
expectedIP := net.ParseIP("2001:db8:f00f:cafe::99")
|
||||||
var expectedPreferredLifetime, expectedValidLifetime uint32 = 27000, 43200
|
var expectedPreferredLifetime, expectedValidLifetime uint32 = 27000, 43200
|
||||||
iaAddrOption := MakeIaAddrOption(expectedIp, expectedPreferredLifetime, expectedValidLifetime)
|
iaAddrOption := MakeIaAddrOption(expectedIP, expectedPreferredLifetime, expectedValidLifetime)
|
||||||
|
|
||||||
if iaAddrOption.Id != OptIaAddr {
|
if iaAddrOption.ID != OptIaAddr {
|
||||||
t.Fatalf("Expected option id %d, got %d", OptIaAddr, iaAddrOption.Id)
|
t.Fatalf("Expected option id %d, got %d", OptIaAddr, iaAddrOption.ID)
|
||||||
}
|
}
|
||||||
if iaAddrOption.Length != 24 {
|
if iaAddrOption.Length != 24 {
|
||||||
t.Fatalf("Expected length 24 bytes, got %d", iaAddrOption.Length)
|
t.Fatalf("Expected length 24 bytes, got %d", iaAddrOption.Length)
|
||||||
}
|
}
|
||||||
if string(iaAddrOption.Value[0:16]) != string(expectedIp) {
|
if string(iaAddrOption.Value[0:16]) != string(expectedIP) {
|
||||||
t.Fatalf("Expected address %v, got %v", expectedIp, iaAddrOption.Value[0:16])
|
t.Fatalf("Expected address %v, got %v", expectedIP, iaAddrOption.Value[0:16])
|
||||||
}
|
}
|
||||||
if preferredLifetime := uint32(binary.BigEndian.Uint32(iaAddrOption.Value[16:20])); preferredLifetime != expectedPreferredLifetime {
|
if preferredLifetime := uint32(binary.BigEndian.Uint32(iaAddrOption.Value[16:20])); preferredLifetime != expectedPreferredLifetime {
|
||||||
t.Fatalf("Expected preferred lifetime of %d, got %d", expectedPreferredLifetime, preferredLifetime)
|
t.Fatalf("Expected preferred lifetime of %d, got %d", expectedPreferredLifetime, preferredLifetime)
|
||||||
@ -55,16 +55,16 @@ func TestMakeIaNaOption(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected serialization error: %s", err)
|
t.Fatalf("Unexpected serialization error: %s", err)
|
||||||
}
|
}
|
||||||
expectedId := []byte("1234")
|
expectedID := []byte("1234")
|
||||||
var expectedT1, expectedT2 uint32 = 100, 200
|
var expectedT1, expectedT2 uint32 = 100, 200
|
||||||
|
|
||||||
iaNaOption := MakeIaNaOption(expectedId, expectedT1, expectedT2, iaAddrOption)
|
iaNaOption := MakeIaNaOption(expectedID, expectedT1, expectedT2, iaAddrOption)
|
||||||
|
|
||||||
if iaNaOption.Id != OptIaNa {
|
if iaNaOption.ID != OptIaNa {
|
||||||
t.Fatalf("Expected optionId %d, got %d", OptIaNa, iaNaOption.Id)
|
t.Fatalf("Expected optionId %d, got %d", OptIaNa, iaNaOption.ID)
|
||||||
}
|
}
|
||||||
if string(iaNaOption.Value[0:4]) != string(expectedId) {
|
if string(iaNaOption.Value[0:4]) != string(expectedID) {
|
||||||
t.Fatalf("Expected id %s, got %s", expectedId, string(iaNaOption.Value[0:4]))
|
t.Fatalf("Expected id %s, got %s", expectedID, string(iaNaOption.Value[0:4]))
|
||||||
}
|
}
|
||||||
if t1 := uint32(binary.BigEndian.Uint32(iaNaOption.Value[4:])); t1 != expectedT1 {
|
if t1 := uint32(binary.BigEndian.Uint32(iaNaOption.Value[4:])); t1 != expectedT1 {
|
||||||
t.Fatalf("Expected t1 of %d, got %d", expectedT1, t1)
|
t.Fatalf("Expected t1 of %d, got %d", expectedT1, t1)
|
||||||
@ -82,8 +82,8 @@ func TestMakeStatusOption(t *testing.T) {
|
|||||||
expectedStatusCode := uint16(2)
|
expectedStatusCode := uint16(2)
|
||||||
noAddrOption := MakeStatusOption(expectedStatusCode, expectedMessage)
|
noAddrOption := MakeStatusOption(expectedStatusCode, expectedMessage)
|
||||||
|
|
||||||
if noAddrOption.Id != OptStatusCode {
|
if noAddrOption.ID != OptStatusCode {
|
||||||
t.Fatalf("Expected option id %d, got %d", OptStatusCode, noAddrOption.Id)
|
t.Fatalf("Expected option id %d, got %d", OptStatusCode, noAddrOption.ID)
|
||||||
}
|
}
|
||||||
if noAddrOption.Length != uint16(2 + len(expectedMessage)) {
|
if noAddrOption.Length != uint16(2 + len(expectedMessage)) {
|
||||||
t.Fatalf("Expected option length of %d, got %d", 2 + len(expectedMessage), noAddrOption.Length)
|
t.Fatalf("Expected option length of %d, got %d", 2 + len(expectedMessage), noAddrOption.Length)
|
||||||
@ -108,8 +108,8 @@ func TestMakeDNSServersOption(t *testing.T) {
|
|||||||
expectedAddress2 := net.ParseIP("2001:db8:f00f:cafe::9A")
|
expectedAddress2 := net.ParseIP("2001:db8:f00f:cafe::9A")
|
||||||
dnsServersOption := MakeDNSServersOption([]net.IP{expectedAddress1, expectedAddress2})
|
dnsServersOption := MakeDNSServersOption([]net.IP{expectedAddress1, expectedAddress2})
|
||||||
|
|
||||||
if dnsServersOption.Id != OptRecursiveDns {
|
if dnsServersOption.ID != OptRecursiveDNS {
|
||||||
t.Fatalf("Expected option id %d, got %d", OptRecursiveDns, dnsServersOption.Id)
|
t.Fatalf("Expected option id %d, got %d", OptRecursiveDNS, dnsServersOption.ID)
|
||||||
}
|
}
|
||||||
if dnsServersOption.Length != 32 {
|
if dnsServersOption.Length != 32 {
|
||||||
t.Fatalf("Expected length 32 bytes, got %d", dnsServersOption.Length)
|
t.Fatalf("Expected length 32 bytes, got %d", dnsServersOption.Length)
|
||||||
|
@ -40,15 +40,15 @@ func MakePacket(bs []byte, packetLength int) (*Packet, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Packet) Marshal() ([]byte, error) {
|
func (p *Packet) Marshal() ([]byte, error) {
|
||||||
marshalled_options, err := p.Options.Marshal()
|
marshalledOptions, err := p.Options.Marshal()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("packet has malformed options section: %s", err)
|
return nil, fmt.Errorf("packet has malformed options section: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ret := make([]byte, len(marshalled_options) + 4, len(marshalled_options) + 4)
|
ret := make([]byte, len(marshalledOptions) + 4, len(marshalledOptions) + 4)
|
||||||
ret[0] = byte(p.Type)
|
ret[0] = byte(p.Type)
|
||||||
copy(ret[1:], p.TransactionID[:])
|
copy(ret[1:], p.TransactionID[:])
|
||||||
copy(ret[4:], marshalled_options)
|
copy(ret[4:], marshalledOptions)
|
||||||
|
|
||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
@ -70,13 +70,13 @@ func (p *Packet) ShouldDiscard(serverDuid []byte) error {
|
|||||||
|
|
||||||
func ShouldDiscardSolicit(p *Packet) error {
|
func ShouldDiscardSolicit(p *Packet) error {
|
||||||
options := p.Options
|
options := p.Options
|
||||||
if !options.HasBootFileUrlOption() {
|
if !options.HasBootFileURLOption() {
|
||||||
return fmt.Errorf("'Solicit' packet doesn't have file url option")
|
return fmt.Errorf("'Solicit' packet doesn't have file url option")
|
||||||
}
|
}
|
||||||
if !options.HasClientId() {
|
if !options.HasClientID() {
|
||||||
return fmt.Errorf("'Solicit' packet has no client id option")
|
return fmt.Errorf("'Solicit' packet has no Client id option")
|
||||||
}
|
}
|
||||||
if options.HasServerId() {
|
if options.HasServerID() {
|
||||||
return fmt.Errorf("'Solicit' packet has server id option")
|
return fmt.Errorf("'Solicit' packet has server id option")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -84,31 +84,31 @@ func ShouldDiscardSolicit(p *Packet) error {
|
|||||||
|
|
||||||
func ShouldDiscardRequest(p *Packet, serverDuid []byte) error {
|
func ShouldDiscardRequest(p *Packet, serverDuid []byte) error {
|
||||||
options := p.Options
|
options := p.Options
|
||||||
if !options.HasBootFileUrlOption() {
|
if !options.HasBootFileURLOption() {
|
||||||
return fmt.Errorf("'Request' packet doesn't have file url option")
|
return fmt.Errorf("'Request' packet doesn't have file url option")
|
||||||
}
|
}
|
||||||
if !options.HasClientId() {
|
if !options.HasClientID() {
|
||||||
return fmt.Errorf("'Request' packet has no client id option")
|
return fmt.Errorf("'Request' packet has no Client id option")
|
||||||
}
|
}
|
||||||
if !options.HasServerId() {
|
if !options.HasServerID() {
|
||||||
return fmt.Errorf("'Request' packet has no server id option")
|
return fmt.Errorf("'Request' packet has no server id option")
|
||||||
}
|
}
|
||||||
if bytes.Compare(options.ServerId(), serverDuid) != 0 {
|
if bytes.Compare(options.ServerID(), serverDuid) != 0 {
|
||||||
return fmt.Errorf("'Request' packet's server id option (%d) is different from ours (%d)", options.ServerId(), serverDuid)
|
return fmt.Errorf("'Request' packet's server id option (%d) is different from ours (%d)", options.ServerID(), serverDuid)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ShouldDiscardInformationRequest(p *Packet, serverDuid []byte) error {
|
func ShouldDiscardInformationRequest(p *Packet, serverDuid []byte) error {
|
||||||
options := p.Options
|
options := p.Options
|
||||||
if !options.HasBootFileUrlOption() {
|
if !options.HasBootFileURLOption() {
|
||||||
return fmt.Errorf("'Information-request' packet doesn't have boot file url option")
|
return fmt.Errorf("'Information-request' packet doesn't have boot file url option")
|
||||||
}
|
}
|
||||||
if options.HasIaNa() || options.HasIaTa() {
|
if options.HasIaNa() || options.HasIaTa() {
|
||||||
return fmt.Errorf("'Information-request' packet has an IA option present")
|
return fmt.Errorf("'Information-request' packet has an IA option present")
|
||||||
}
|
}
|
||||||
if options.HasServerId() && (bytes.Compare(options.ServerId(), serverDuid) != 0) {
|
if options.HasServerID() && (bytes.Compare(options.ServerID(), serverDuid) != 0) {
|
||||||
return fmt.Errorf("'Information-request' packet's server id option (%d) is different from ours (%d)", options.ServerId(), serverDuid)
|
return fmt.Errorf("'Information-request' packet's server id option (%d) is different from ours (%d)", options.ServerID(), serverDuid)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -15,116 +15,117 @@ func MakePacketBuilder(preferredLifetime, validLifetime uint32) *PacketBuilder {
|
|||||||
return &PacketBuilder{PreferredLifetime: preferredLifetime, ValidLifetime: validLifetime}
|
return &PacketBuilder{PreferredLifetime: preferredLifetime, ValidLifetime: validLifetime}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *PacketBuilder) BuildResponse(in *Packet, serverDuid []byte, configuration BootConfiguration, addresses AddressPool) (*Packet, error) {
|
func (b *PacketBuilder) BuildResponse(in *Packet, serverDUID []byte, configuration BootConfiguration, addresses AddressPool) (*Packet, error) {
|
||||||
switch in.Type {
|
switch in.Type {
|
||||||
case MsgSolicit:
|
case MsgSolicit:
|
||||||
bootFileUrl, err := configuration.GetBootUrl(b.ExtractLLAddressOrId(in.Options.ClientId()), in.Options.ClientArchType())
|
bootFileURL, err := configuration.GetBootURL(b.ExtractLLAddressOrID(in.Options.ClientID()), in.Options.ClientArchType())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
associations, err := addresses.ReserveAddresses(in.Options.ClientId(), in.Options.IaNaIds())
|
associations, err := addresses.ReserveAddresses(in.Options.ClientID(), in.Options.IaNaIDs())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return b.MakeMsgAdvertiseWithNoAddrsAvailable(in.TransactionID, serverDuid, in.Options.ClientId(), err), err
|
return b.MakeMsgAdvertiseWithNoAddrsAvailable(in.TransactionID, serverDUID, in.Options.ClientID(), err), err
|
||||||
}
|
}
|
||||||
return b.MakeMsgAdvertise(in.TransactionID, serverDuid, in.Options.ClientId(),
|
return b.MakeMsgAdvertise(in.TransactionID, serverDUID, in.Options.ClientID(),
|
||||||
in.Options.ClientArchType(), associations, bootFileUrl, configuration.GetPreference(), configuration.GetRecursiveDns()), nil
|
in.Options.ClientArchType(), associations, bootFileURL, configuration.GetPreference(), configuration.GetRecursiveDNS()), nil
|
||||||
case MsgRequest:
|
case MsgRequest:
|
||||||
bootFileUrl, err := configuration.GetBootUrl(b.ExtractLLAddressOrId(in.Options.ClientId()), in.Options.ClientArchType())
|
bootFileURL, err := configuration.GetBootURL(b.ExtractLLAddressOrID(in.Options.ClientID()), in.Options.ClientArchType())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
associations, err := addresses.ReserveAddresses(in.Options.ClientId(), in.Options.IaNaIds())
|
associations, err := addresses.ReserveAddresses(in.Options.ClientID(), in.Options.IaNaIDs())
|
||||||
return b.MakeMsgReply(in.TransactionID, serverDuid, in.Options.ClientId(),
|
return b.MakeMsgReply(in.TransactionID, serverDUID, in.Options.ClientID(),
|
||||||
in.Options.ClientArchType(), associations, iasWithoutAddesses(associations, in.Options.IaNaIds()), bootFileUrl,
|
in.Options.ClientArchType(), associations, iasWithoutAddesses(associations, in.Options.IaNaIDs()), bootFileURL,
|
||||||
configuration.GetRecursiveDns(), err), err
|
configuration.GetRecursiveDNS(), err), err
|
||||||
case MsgInformationRequest:
|
case MsgInformationRequest:
|
||||||
bootFileUrl, err := configuration.GetBootUrl(b.ExtractLLAddressOrId(in.Options.ClientId()), in.Options.ClientArchType())
|
bootFileURL, err := configuration.GetBootURL(b.ExtractLLAddressOrID(in.Options.ClientID()), in.Options.ClientArchType())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return b.MakeMsgInformationRequestReply(in.TransactionID, serverDuid, in.Options.ClientId(),
|
return b.MakeMsgInformationRequestReply(in.TransactionID, serverDUID, in.Options.ClientID(),
|
||||||
in.Options.ClientArchType(), bootFileUrl, configuration.GetRecursiveDns()), nil
|
in.Options.ClientArchType(), bootFileURL, configuration.GetRecursiveDNS()), nil
|
||||||
case MsgRelease:
|
case MsgRelease:
|
||||||
addresses.ReleaseAddresses(in.Options.ClientId(), in.Options.IaNaIds())
|
addresses.ReleaseAddresses(in.Options.ClientID(), in.Options.IaNaIDs())
|
||||||
return b.MakeMsgReleaseReply(in.TransactionID, serverDuid, in.Options.ClientId()), nil
|
return b.MakeMsgReleaseReply(in.TransactionID, serverDUID, in.Options.ClientID()), nil
|
||||||
default:
|
default:
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *PacketBuilder) MakeMsgAdvertise(transactionId [3]byte, serverDuid, clientId []byte, clientArchType uint16,
|
func (b *PacketBuilder) MakeMsgAdvertise(transactionID [3]byte, serverDUID, clientID []byte, clientArchType uint16,
|
||||||
associations []*IdentityAssociation, bootFileUrl, preference []byte, dnsServers []net.IP) *Packet {
|
associations []*IdentityAssociation, bootFileURL, preference []byte, dnsServers []net.IP) *Packet {
|
||||||
ret_options := make(Options)
|
retOptions := make(Options)
|
||||||
ret_options.AddOption(MakeOption(OptClientId, clientId))
|
retOptions.AddOption(MakeOption(OptClientID, clientID))
|
||||||
for _, association := range(associations) {
|
for _, association := range(associations) {
|
||||||
ret_options.AddOption(MakeIaNaOption(association.InterfaceId, b.calculateT1(), b.calculateT2(),
|
retOptions.AddOption(MakeIaNaOption(association.InterfaceID, b.calculateT1(), b.calculateT2(),
|
||||||
MakeIaAddrOption(association.IpAddress, b.PreferredLifetime, b.ValidLifetime)))
|
MakeIaAddrOption(association.IPAddress, b.PreferredLifetime, b.ValidLifetime)))
|
||||||
}
|
}
|
||||||
ret_options.AddOption(MakeOption(OptServerId, serverDuid))
|
retOptions.AddOption(MakeOption(OptServerID, serverDUID))
|
||||||
if 0x10 == clientArchType { // HTTPClient
|
if 0x10 == clientArchType { // HTTPClient
|
||||||
ret_options.AddOption(MakeOption(OptVendorClass, []byte {0, 0, 0, 0, 0, 10, 72, 84, 84, 80, 67, 108, 105, 101, 110, 116})) // HTTPClient
|
retOptions.AddOption(MakeOption(OptVendorClass, []byte {0, 0, 0, 0, 0, 10, 72, 84, 84, 80, 67, 108, 105, 101, 110, 116})) // HTTPClient
|
||||||
}
|
}
|
||||||
ret_options.AddOption(MakeOption(OptBootfileUrl, bootFileUrl))
|
retOptions.AddOption(MakeOption(OptBootfileURL, bootFileURL))
|
||||||
if preference != nil {ret_options.AddOption(MakeOption(OptPreference, preference))}
|
if preference != nil {
|
||||||
if len(dnsServers) > 0 { ret_options.AddOption(MakeDNSServersOption(dnsServers)) }
|
retOptions.AddOption(MakeOption(OptPreference, preference))}
|
||||||
|
if len(dnsServers) > 0 { retOptions.AddOption(MakeDNSServersOption(dnsServers)) }
|
||||||
|
|
||||||
return &Packet{Type: MsgAdvertise, TransactionID: transactionId, Options: ret_options}
|
return &Packet{Type: MsgAdvertise, TransactionID: transactionID, Options: retOptions}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *PacketBuilder) MakeMsgReply(transactionId [3]byte, serverDuid, clientId []byte, clientArchType uint16,
|
func (b *PacketBuilder) MakeMsgReply(transactionID [3]byte, serverDUID, clientID []byte, clientArchType uint16,
|
||||||
associations []*IdentityAssociation, iasWithoutAddresses [][]byte, bootFileUrl []byte, dnsServers []net.IP, err error) *Packet {
|
associations []*IdentityAssociation, iasWithoutAddresses [][]byte, bootFileURL []byte, dnsServers []net.IP, err error) *Packet {
|
||||||
ret_options := make(Options)
|
retOptions := make(Options)
|
||||||
ret_options.AddOption(MakeOption(OptClientId, clientId))
|
retOptions.AddOption(MakeOption(OptClientID, clientID))
|
||||||
for _, association := range(associations) {
|
for _, association := range(associations) {
|
||||||
ret_options.AddOption(MakeIaNaOption(association.InterfaceId, b.calculateT1(), b.calculateT2(),
|
retOptions.AddOption(MakeIaNaOption(association.InterfaceID, b.calculateT1(), b.calculateT2(),
|
||||||
MakeIaAddrOption(association.IpAddress, b.PreferredLifetime, b.ValidLifetime)))
|
MakeIaAddrOption(association.IPAddress, b.PreferredLifetime, b.ValidLifetime)))
|
||||||
}
|
}
|
||||||
for _, ia := range(iasWithoutAddresses) {
|
for _, ia := range(iasWithoutAddresses) {
|
||||||
ret_options.AddOption(MakeIaNaOption(ia, b.calculateT1(), b.calculateT2(),
|
retOptions.AddOption(MakeIaNaOption(ia, b.calculateT1(), b.calculateT2(),
|
||||||
MakeStatusOption(2, err.Error())))
|
MakeStatusOption(2, err.Error())))
|
||||||
}
|
}
|
||||||
ret_options.AddOption(MakeOption(OptServerId, serverDuid))
|
retOptions.AddOption(MakeOption(OptServerID, serverDUID))
|
||||||
if 0x10 == clientArchType { // HTTPClient
|
if 0x10 == clientArchType { // HTTPClient
|
||||||
ret_options.AddOption(MakeOption(OptVendorClass, []byte {0, 0, 0, 0, 0, 10, 72, 84, 84, 80, 67, 108, 105, 101, 110, 116})) // HTTPClient
|
retOptions.AddOption(MakeOption(OptVendorClass, []byte {0, 0, 0, 0, 0, 10, 72, 84, 84, 80, 67, 108, 105, 101, 110, 116})) // HTTPClient
|
||||||
}
|
}
|
||||||
ret_options.AddOption(MakeOption(OptBootfileUrl, bootFileUrl))
|
retOptions.AddOption(MakeOption(OptBootfileURL, bootFileURL))
|
||||||
if len(dnsServers) > 0 { ret_options.AddOption(MakeDNSServersOption(dnsServers)) }
|
if len(dnsServers) > 0 { retOptions.AddOption(MakeDNSServersOption(dnsServers)) }
|
||||||
|
|
||||||
return &Packet{Type: MsgReply, TransactionID: transactionId, Options: ret_options}
|
return &Packet{Type: MsgReply, TransactionID: transactionID, Options: retOptions}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *PacketBuilder) MakeMsgInformationRequestReply(transactionId [3]byte, serverDuid, clientId []byte, clientArchType uint16,
|
func (b *PacketBuilder) MakeMsgInformationRequestReply(transactionID [3]byte, serverDUID, clientID []byte, clientArchType uint16,
|
||||||
bootFileUrl []byte, dnsServers []net.IP) *Packet {
|
bootFileURL []byte, dnsServers []net.IP) *Packet {
|
||||||
ret_options := make(Options)
|
retOptions := make(Options)
|
||||||
ret_options.AddOption(MakeOption(OptClientId, clientId))
|
retOptions.AddOption(MakeOption(OptClientID, clientID))
|
||||||
ret_options.AddOption(MakeOption(OptServerId, serverDuid))
|
retOptions.AddOption(MakeOption(OptServerID, serverDUID))
|
||||||
if 0x10 == clientArchType { // HTTPClient
|
if 0x10 == clientArchType { // HTTPClient
|
||||||
ret_options.AddOption(MakeOption(OptVendorClass, []byte {0, 0, 0, 0, 0, 10, 72, 84, 84, 80, 67, 108, 105, 101, 110, 116})) // HTTPClient
|
retOptions.AddOption(MakeOption(OptVendorClass, []byte {0, 0, 0, 0, 0, 10, 72, 84, 84, 80, 67, 108, 105, 101, 110, 116})) // HTTPClient
|
||||||
}
|
}
|
||||||
ret_options.AddOption(MakeOption(OptBootfileUrl, bootFileUrl))
|
retOptions.AddOption(MakeOption(OptBootfileURL, bootFileURL))
|
||||||
if len(dnsServers) > 0 { ret_options.AddOption(MakeDNSServersOption(dnsServers)) }
|
if len(dnsServers) > 0 { retOptions.AddOption(MakeDNSServersOption(dnsServers)) }
|
||||||
|
|
||||||
return &Packet{Type: MsgReply, TransactionID: transactionId, Options: ret_options}
|
return &Packet{Type: MsgReply, TransactionID: transactionID, Options: retOptions}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *PacketBuilder) MakeMsgReleaseReply(transactionId [3]byte, serverDuid, clientId []byte) *Packet {
|
func (b *PacketBuilder) MakeMsgReleaseReply(transactionID [3]byte, serverDUID, clientID []byte) *Packet {
|
||||||
ret_options := make(Options)
|
retOptions := make(Options)
|
||||||
|
|
||||||
ret_options.AddOption(MakeOption(OptClientId, clientId))
|
retOptions.AddOption(MakeOption(OptClientID, clientID))
|
||||||
ret_options.AddOption(MakeOption(OptServerId, serverDuid))
|
retOptions.AddOption(MakeOption(OptServerID, serverDUID))
|
||||||
v := make([]byte, 19, 19)
|
v := make([]byte, 19, 19)
|
||||||
copy(v[2:], []byte("Release received."))
|
copy(v[2:], []byte("Release received."))
|
||||||
ret_options.AddOption(MakeOption(OptStatusCode, v))
|
retOptions.AddOption(MakeOption(OptStatusCode, v))
|
||||||
|
|
||||||
return &Packet{Type: MsgReply, TransactionID: transactionId, Options: ret_options}
|
return &Packet{Type: MsgReply, TransactionID: transactionID, Options: retOptions}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *PacketBuilder) MakeMsgAdvertiseWithNoAddrsAvailable(transactionId [3]byte, serverDuid, clientId []byte, err error) *Packet {
|
func (b *PacketBuilder) MakeMsgAdvertiseWithNoAddrsAvailable(transactionID [3]byte, serverDUID, clientID []byte, err error) *Packet {
|
||||||
ret_options := make(Options)
|
retOptions := make(Options)
|
||||||
ret_options.AddOption(MakeOption(OptClientId, clientId))
|
retOptions.AddOption(MakeOption(OptClientID, clientID))
|
||||||
ret_options.AddOption(MakeOption(OptServerId, serverDuid))
|
retOptions.AddOption(MakeOption(OptServerID, serverDUID))
|
||||||
ret_options.AddOption(MakeStatusOption(2, err.Error())) // NoAddrAvailable
|
retOptions.AddOption(MakeStatusOption(2, err.Error())) // NoAddrAvailable
|
||||||
return &Packet{Type: MsgAdvertise, TransactionID: transactionId, Options: ret_options}
|
return &Packet{Type: MsgAdvertise, TransactionID: transactionID, Options: retOptions}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *PacketBuilder) calculateT1() uint32 {
|
func (b *PacketBuilder) calculateT1() uint32 {
|
||||||
@ -135,36 +136,36 @@ func (b *PacketBuilder) calculateT2() uint32 {
|
|||||||
return (b.PreferredLifetime * 4)/5
|
return (b.PreferredLifetime * 4)/5
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *PacketBuilder) ExtractLLAddressOrId(optClientId []byte) []byte {
|
func (b *PacketBuilder) ExtractLLAddressOrID(optClientID []byte) []byte {
|
||||||
idType := binary.BigEndian.Uint16(optClientId[0:2])
|
idType := binary.BigEndian.Uint16(optClientID[0:2])
|
||||||
switch idType {
|
switch idType {
|
||||||
case 1:
|
case 1:
|
||||||
return optClientId[8:]
|
return optClientID[8:]
|
||||||
case 3:
|
case 3:
|
||||||
return optClientId[4:]
|
return optClientID[4:]
|
||||||
default:
|
default:
|
||||||
return optClientId[2:]
|
return optClientID[2:]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func iasWithoutAddesses(availableAssociations []*IdentityAssociation, allIas [][]byte) [][]byte {
|
func iasWithoutAddesses(availableAssociations []*IdentityAssociation, allIAs [][]byte) [][]byte {
|
||||||
ret := make([][]byte, 0)
|
ret := make([][]byte, 0)
|
||||||
iasWithAddresses := make(map[uint64]bool)
|
iasWithAddresses := make(map[uint64]bool)
|
||||||
|
|
||||||
for _, association := range(availableAssociations) {
|
for _, association := range(availableAssociations) {
|
||||||
iasWithAddresses[calculateIaIdHash(association.InterfaceId)] = true
|
iasWithAddresses[calculateIAIDHash(association.InterfaceID)] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, ia := range(allIas) {
|
for _, ia := range(allIAs) {
|
||||||
_, exists := iasWithAddresses[calculateIaIdHash(ia)]; if !exists {
|
_, exists := iasWithAddresses[calculateIAIDHash(ia)]; if !exists {
|
||||||
ret = append(ret, ia)
|
ret = append(ret, ia)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func calculateIaIdHash(interfaceId []byte) uint64 {
|
func calculateIAIDHash(interfaceID []byte) uint64 {
|
||||||
h := fnv.New64a()
|
h := fnv.New64a()
|
||||||
h.Write(interfaceId)
|
h.Write(interfaceID)
|
||||||
return h.Sum64()
|
return h.Sum64()
|
||||||
}
|
}
|
||||||
|
@ -8,52 +8,52 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestMakeMsgAdvertise(t *testing.T) {
|
func TestMakeMsgAdvertise(t *testing.T) {
|
||||||
expectedClientId := []byte("clientid")
|
expectedClientID := []byte("clientid")
|
||||||
expectedServerId := []byte("serverid")
|
expectedServerID := []byte("serverid")
|
||||||
expectedInterfaceId := []byte("id-1")
|
expectedInterfaceID := []byte("id-1")
|
||||||
transactionId := [3]byte{'1', '2', '3'}
|
transactionID := [3]byte{'1', '2', '3'}
|
||||||
expectedIp := net.ParseIP("2001:db8:f00f:cafe::1")
|
expectedIP := net.ParseIP("2001:db8:f00f:cafe::1")
|
||||||
expectedBootFileUrl := []byte("http://bootfileurl")
|
expectedBootFileURL := []byte("http://bootfileurl")
|
||||||
expectedDnsServerIp := net.ParseIP("2001:db8:f00f:cafe::99")
|
expectedDnsServerIP := net.ParseIP("2001:db8:f00f:cafe::99")
|
||||||
identityAssociation := &IdentityAssociation{IpAddress: expectedIp, InterfaceId: expectedInterfaceId}
|
identityAssociation := &IdentityAssociation{IPAddress: expectedIP, InterfaceID: expectedInterfaceID}
|
||||||
|
|
||||||
builder := MakePacketBuilder(90, 100)
|
builder := MakePacketBuilder(90, 100)
|
||||||
|
|
||||||
msg := builder.MakeMsgAdvertise(transactionId, expectedServerId, expectedClientId, 0x11,
|
msg := builder.MakeMsgAdvertise(transactionID, expectedServerID, expectedClientID, 0x11,
|
||||||
[]*IdentityAssociation{identityAssociation}, expectedBootFileUrl, nil, []net.IP{expectedDnsServerIp})
|
[]*IdentityAssociation{identityAssociation}, expectedBootFileURL, nil, []net.IP{expectedDnsServerIP})
|
||||||
|
|
||||||
if msg.Type != MsgAdvertise {
|
if msg.Type != MsgAdvertise {
|
||||||
t.Fatalf("Expected message type %d, got %d", MsgAdvertise, msg.Type)
|
t.Fatalf("Expected message type %d, got %d", MsgAdvertise, msg.Type)
|
||||||
}
|
}
|
||||||
if transactionId != msg.TransactionID {
|
if transactionID != msg.TransactionID {
|
||||||
t.Fatalf("Expected transaction Id %v, got %v", transactionId, msg.TransactionID)
|
t.Fatalf("Expected transaction ID %v, got %v", transactionID, msg.TransactionID)
|
||||||
}
|
}
|
||||||
|
|
||||||
clientIdOption := msg.Options.ClientId()
|
clientIDOption := msg.Options.ClientID()
|
||||||
if clientIdOption == nil {
|
if clientIDOption == nil {
|
||||||
t.Fatalf("Client Id option should be present")
|
t.Fatalf("Client ID option should be present")
|
||||||
}
|
}
|
||||||
if string(expectedClientId) != string(clientIdOption) {
|
if string(expectedClientID) != string(clientIDOption) {
|
||||||
t.Fatalf("Expected client id %v, got %v", expectedClientId, clientIdOption)
|
t.Fatalf("Expected Client id %v, got %v", expectedClientID, clientIDOption)
|
||||||
}
|
}
|
||||||
|
|
||||||
serverIdOption := msg.Options.ServerId()
|
serverIDOption := msg.Options.ServerID()
|
||||||
if serverIdOption == nil {
|
if serverIDOption == nil {
|
||||||
t.Fatalf("Server Id option should be present")
|
t.Fatalf("Server ID option should be present")
|
||||||
}
|
}
|
||||||
if string(expectedServerId) != string(serverIdOption) {
|
if string(expectedServerID) != string(serverIDOption) {
|
||||||
t.Fatalf("Expected server id %v, got %v", expectedClientId, serverIdOption)
|
t.Fatalf("Expected server id %v, got %v", expectedClientID, serverIDOption)
|
||||||
}
|
}
|
||||||
|
|
||||||
bootfileUrlOption := msg.Options[OptBootfileUrl][0]
|
bootfileURLOption := msg.Options[OptBootfileURL][0]
|
||||||
if bootfileUrlOption == nil {
|
if bootfileURLOption == nil {
|
||||||
t.Fatalf("Bootfile URL option should be present")
|
t.Fatalf("Bootfile URL option should be present")
|
||||||
}
|
}
|
||||||
if string(expectedBootFileUrl) != string(bootfileUrlOption.Value) {
|
if string(expectedBootFileURL) != string(bootfileURLOption.Value) {
|
||||||
t.Fatalf("Expected bootfile URL %v, got %v", expectedBootFileUrl, bootfileUrlOption)
|
t.Fatalf("Expected bootfile URL %v, got %v", expectedBootFileURL, bootfileURLOption)
|
||||||
}
|
}
|
||||||
|
|
||||||
iaNaOption := msg.Options.IaNaIds()
|
iaNaOption := msg.Options.IaNaIDs()
|
||||||
if len(iaNaOption) == 0 {
|
if len(iaNaOption) == 0 {
|
||||||
t.Fatalf("interface non-temporary association option should be present")
|
t.Fatalf("interface non-temporary association option should be present")
|
||||||
}
|
}
|
||||||
@ -63,36 +63,36 @@ func TestMakeMsgAdvertise(t *testing.T) {
|
|||||||
t.Fatalf("Preference option shouldn't be set")
|
t.Fatalf("Preference option shouldn't be set")
|
||||||
}
|
}
|
||||||
|
|
||||||
dnsServersOption := msg.Options[OptRecursiveDns]
|
dnsServersOption := msg.Options[OptRecursiveDNS]
|
||||||
if dnsServersOption == nil {
|
if dnsServersOption == nil {
|
||||||
t.Fatalf("DNS servers option should be set")
|
t.Fatalf("DNS servers option should be set")
|
||||||
}
|
}
|
||||||
if string(dnsServersOption[0].Value) != string(expectedDnsServerIp) {
|
if string(dnsServersOption[0].Value) != string(expectedDnsServerIP) {
|
||||||
t.Fatalf("Expected dns server %v, got %v", expectedDnsServerIp, net.IP(dnsServersOption[0].Value))
|
t.Fatalf("Expected dns server %v, got %v", expectedDnsServerIP, net.IP(dnsServersOption[0].Value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMakeMsgAdvertiseShouldSkipDnsServersIfNoneConfigured(t *testing.T) {
|
func TestMakeMsgAdvertiseShouldSkipDnsServersIfNoneConfigured(t *testing.T) {
|
||||||
expectedClientId := []byte("clientid")
|
expectedClientID := []byte("clientid")
|
||||||
expectedServerId := []byte("serverid")
|
expectedServerID := []byte("serverid")
|
||||||
expectedInterfaceId := []byte("id-1")
|
expectedInterfaceID := []byte("id-1")
|
||||||
transactionId := [3]byte{'1', '2', '3'}
|
transactionID := [3]byte{'1', '2', '3'}
|
||||||
expectedIp := net.ParseIP("2001:db8:f00f:cafe::1")
|
expectedIP := net.ParseIP("2001:db8:f00f:cafe::1")
|
||||||
expectedBootFileUrl := []byte("http://bootfileurl")
|
expectedBootFileURL := []byte("http://bootfileurl")
|
||||||
identityAssociation := &IdentityAssociation{IpAddress: expectedIp, InterfaceId: expectedInterfaceId}
|
identityAssociation := &IdentityAssociation{IPAddress: expectedIP, InterfaceID: expectedInterfaceID}
|
||||||
|
|
||||||
builder := MakePacketBuilder(90, 100)
|
builder := MakePacketBuilder(90, 100)
|
||||||
|
|
||||||
msg := builder.MakeMsgAdvertise(transactionId, expectedServerId, expectedClientId, 0x11,
|
msg := builder.MakeMsgAdvertise(transactionID, expectedServerID, expectedClientID, 0x11,
|
||||||
[]*IdentityAssociation{identityAssociation}, expectedBootFileUrl, nil, []net.IP{})
|
[]*IdentityAssociation{identityAssociation}, expectedBootFileURL, nil, []net.IP{})
|
||||||
|
|
||||||
_, exists := msg.Options[OptRecursiveDns]; if exists {
|
_, exists := msg.Options[OptRecursiveDNS]; if exists {
|
||||||
t.Fatalf("DNS servers option should not be set")
|
t.Fatalf("DNS servers option should not be set")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestShouldSetPreferenceOptionWhenSpecified(t *testing.T) {
|
func TestShouldSetPreferenceOptionWhenSpecified(t *testing.T) {
|
||||||
identityAssociation := &IdentityAssociation{IpAddress: net.ParseIP("2001:db8:f00f:cafe::1"), InterfaceId: []byte("id-1")}
|
identityAssociation := &IdentityAssociation{IPAddress: net.ParseIP("2001:db8:f00f:cafe::1"), InterfaceID: []byte("id-1")}
|
||||||
|
|
||||||
builder := MakePacketBuilder(90, 100)
|
builder := MakePacketBuilder(90, 100)
|
||||||
|
|
||||||
@ -110,62 +110,62 @@ func TestShouldSetPreferenceOptionWhenSpecified(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestMakeMsgAdvertiseWithHttpClientArch(t *testing.T) {
|
func TestMakeMsgAdvertiseWithHttpClientArch(t *testing.T) {
|
||||||
expectedClientId := []byte("clientid")
|
expectedClientID := []byte("clientid")
|
||||||
expectedServerId := []byte("serverid")
|
expectedServerID := []byte("serverid")
|
||||||
transactionId := [3]byte{'1', '2', '3'}
|
transactionID := [3]byte{'1', '2', '3'}
|
||||||
expectedIp := net.ParseIP("2001:db8:f00f:cafe::1")
|
expectedIP := net.ParseIP("2001:db8:f00f:cafe::1")
|
||||||
expectedBootFileUrl := []byte("http://bootfileurl")
|
expectedBootFileURL := []byte("http://bootfileurl")
|
||||||
identityAssociation := &IdentityAssociation{IpAddress: expectedIp, InterfaceId: []byte("id-1")}
|
identityAssociation := &IdentityAssociation{IPAddress: expectedIP, InterfaceID: []byte("id-1")}
|
||||||
|
|
||||||
builder := MakePacketBuilder(90, 100)
|
builder := MakePacketBuilder(90, 100)
|
||||||
|
|
||||||
msg := builder.MakeMsgAdvertise(transactionId, expectedServerId, expectedClientId, 0x10,
|
msg := builder.MakeMsgAdvertise(transactionID, expectedServerID, expectedClientID, 0x10,
|
||||||
[]*IdentityAssociation{identityAssociation}, expectedBootFileUrl, nil, []net.IP{})
|
[]*IdentityAssociation{identityAssociation}, expectedBootFileURL, nil, []net.IP{})
|
||||||
|
|
||||||
vendorClassOption := msg.Options[OptVendorClass]
|
vendorClassOption := msg.Options[OptVendorClass]
|
||||||
if vendorClassOption == nil {
|
if vendorClassOption == nil {
|
||||||
t.Fatalf("Vendor class option should be present")
|
t.Fatalf("Vendor class option should be present")
|
||||||
}
|
}
|
||||||
bootfileUrlOption := msg.Options.BootfileUrl()
|
bootfileURLOption := msg.Options.BootFileURL()
|
||||||
if bootfileUrlOption == nil {
|
if bootfileURLOption == nil {
|
||||||
t.Fatalf("Bootfile URL option should be present")
|
t.Fatalf("Bootfile URL option should be present")
|
||||||
}
|
}
|
||||||
if string(expectedBootFileUrl) != string(bootfileUrlOption) {
|
if string(expectedBootFileURL) != string(bootfileURLOption) {
|
||||||
t.Fatalf("Expected bootfile URL %s, got %s", expectedBootFileUrl, bootfileUrlOption)
|
t.Fatalf("Expected bootfile URL %s, got %s", expectedBootFileURL, bootfileURLOption)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMakeNoAddrsAvailable(t *testing.T) {
|
func TestMakeNoAddrsAvailable(t *testing.T) {
|
||||||
expectedClientId := []byte("clientid")
|
expectedClientID := []byte("clientid")
|
||||||
expectedServerId := []byte("serverid")
|
expectedServerID := []byte("serverid")
|
||||||
transactionId := [3]byte{'1', '2', '3'}
|
transactionID := [3]byte{'1', '2', '3'}
|
||||||
expectedMessage := "Boom!"
|
expectedMessage := "Boom!"
|
||||||
|
|
||||||
builder := MakePacketBuilder(90, 100)
|
builder := MakePacketBuilder(90, 100)
|
||||||
|
|
||||||
msg := builder.MakeMsgAdvertiseWithNoAddrsAvailable(transactionId, expectedServerId, expectedClientId, fmt.Errorf(expectedMessage))
|
msg := builder.MakeMsgAdvertiseWithNoAddrsAvailable(transactionID, expectedServerID, expectedClientID, fmt.Errorf(expectedMessage))
|
||||||
|
|
||||||
if msg.Type != MsgAdvertise {
|
if msg.Type != MsgAdvertise {
|
||||||
t.Fatalf("Expected message type %d, got %d", MsgAdvertise, msg.Type)
|
t.Fatalf("Expected message type %d, got %d", MsgAdvertise, msg.Type)
|
||||||
}
|
}
|
||||||
if transactionId != msg.TransactionID {
|
if transactionID != msg.TransactionID {
|
||||||
t.Fatalf("Expected transaction Id %v, got %v", transactionId, msg.TransactionID)
|
t.Fatalf("Expected transaction ID %v, got %v", transactionID, msg.TransactionID)
|
||||||
}
|
}
|
||||||
|
|
||||||
clientIdOption := msg.Options.ClientId()
|
clientIDOption := msg.Options.ClientID()
|
||||||
if clientIdOption == nil {
|
if clientIDOption == nil {
|
||||||
t.Fatalf("Client Id option should be present")
|
t.Fatalf("Client ID option should be present")
|
||||||
}
|
}
|
||||||
if string(expectedClientId) != string(clientIdOption) {
|
if string(expectedClientID) != string(clientIDOption) {
|
||||||
t.Fatalf("Expected client id %v, got %v", expectedClientId, clientIdOption)
|
t.Fatalf("Expected Client id %v, got %v", expectedClientID, clientIDOption)
|
||||||
}
|
}
|
||||||
|
|
||||||
serverIdOption := msg.Options.ServerId()
|
serverIDOption := msg.Options.ServerID()
|
||||||
if serverIdOption == nil {
|
if serverIDOption == nil {
|
||||||
t.Fatalf("Server Id option should be present")
|
t.Fatalf("Server ID option should be present")
|
||||||
}
|
}
|
||||||
if string(expectedServerId) != string(serverIdOption) {
|
if string(expectedServerID) != string(serverIDOption) {
|
||||||
t.Fatalf("Expected server id %v, got %v", expectedClientId, serverIdOption)
|
t.Fatalf("Expected server id %v, got %v", expectedClientID, serverIDOption)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, exists := msg.Options[OptStatusCode]; if !exists {
|
_, exists := msg.Options[OptStatusCode]; if !exists {
|
||||||
@ -181,54 +181,54 @@ func TestMakeNoAddrsAvailable(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestMakeMsgReply(t *testing.T) {
|
func TestMakeMsgReply(t *testing.T) {
|
||||||
expectedClientId := []byte("clientid")
|
expectedClientID := []byte("clientid")
|
||||||
expectedServerId := []byte("serverid")
|
expectedServerID := []byte("serverid")
|
||||||
transactionId := [3]byte{'1', '2', '3'}
|
transactionID := [3]byte{'1', '2', '3'}
|
||||||
expectedIp := net.ParseIP("2001:db8:f00f:cafe::1")
|
expectedIP := net.ParseIP("2001:db8:f00f:cafe::1")
|
||||||
expectedBootFileUrl := []byte("http://bootfileurl")
|
expectedBootFileURL := []byte("http://bootfileurl")
|
||||||
expectedDnsServerIp := net.ParseIP("2001:db8:f00f:cafe::99")
|
expectedDnsServerIP := net.ParseIP("2001:db8:f00f:cafe::99")
|
||||||
identityAssociation := &IdentityAssociation{IpAddress: expectedIp, InterfaceId: []byte("id-1")}
|
identityAssociation := &IdentityAssociation{IPAddress: expectedIP, InterfaceID: []byte("id-1")}
|
||||||
|
|
||||||
builder := MakePacketBuilder(90, 100)
|
builder := MakePacketBuilder(90, 100)
|
||||||
|
|
||||||
msg := builder.MakeMsgReply(transactionId, expectedServerId, expectedClientId, 0x11,
|
msg := builder.MakeMsgReply(transactionID, expectedServerID, expectedClientID, 0x11,
|
||||||
[]*IdentityAssociation{identityAssociation}, make([][]byte, 0), expectedBootFileUrl, []net.IP{expectedDnsServerIp}, nil)
|
[]*IdentityAssociation{identityAssociation}, make([][]byte, 0), expectedBootFileURL, []net.IP{expectedDnsServerIP}, nil)
|
||||||
|
|
||||||
if msg.Type != MsgReply {
|
if msg.Type != MsgReply {
|
||||||
t.Fatalf("Expected message type %d, got %d", MsgAdvertise, msg.Type)
|
t.Fatalf("Expected message type %d, got %d", MsgAdvertise, msg.Type)
|
||||||
}
|
}
|
||||||
if transactionId != msg.TransactionID {
|
if transactionID != msg.TransactionID {
|
||||||
t.Fatalf("Expected transaction Id %v, got %v", transactionId, msg.TransactionID)
|
t.Fatalf("Expected transaction ID %v, got %v", transactionID, msg.TransactionID)
|
||||||
}
|
}
|
||||||
|
|
||||||
clientIdOption := msg.Options.ClientId()
|
clientIDOption := msg.Options.ClientID()
|
||||||
if clientIdOption == nil {
|
if clientIDOption == nil {
|
||||||
t.Fatalf("Client Id option should be present")
|
t.Fatalf("Client ID option should be present")
|
||||||
}
|
}
|
||||||
if string(expectedClientId) != string(clientIdOption) {
|
if string(expectedClientID) != string(clientIDOption) {
|
||||||
t.Fatalf("Expected client id %v, got %v", expectedClientId, clientIdOption)
|
t.Fatalf("Expected Client id %v, got %v", expectedClientID, clientIDOption)
|
||||||
}
|
}
|
||||||
if len(expectedClientId) != len(clientIdOption) {
|
if len(expectedClientID) != len(clientIDOption) {
|
||||||
t.Fatalf("Expected client id length of %d, got %d", len(expectedClientId), len(clientIdOption))
|
t.Fatalf("Expected Client id length of %d, got %d", len(expectedClientID), len(clientIDOption))
|
||||||
}
|
}
|
||||||
|
|
||||||
serverIdOption := msg.Options.ServerId()
|
serverIDOption := msg.Options.ServerID()
|
||||||
if serverIdOption == nil {
|
if serverIDOption == nil {
|
||||||
t.Fatalf("Server Id option should be present")
|
t.Fatalf("Server ID option should be present")
|
||||||
}
|
}
|
||||||
if string(expectedServerId) != string(serverIdOption) {
|
if string(expectedServerID) != string(serverIDOption) {
|
||||||
t.Fatalf("Expected server id %v, got %v", expectedClientId, serverIdOption)
|
t.Fatalf("Expected server id %v, got %v", expectedClientID, serverIDOption)
|
||||||
}
|
}
|
||||||
if len(expectedServerId) != len(serverIdOption) {
|
if len(expectedServerID) != len(serverIDOption) {
|
||||||
t.Fatalf("Expected server id length of %d, got %d", len(expectedClientId), len(serverIdOption))
|
t.Fatalf("Expected server id length of %d, got %d", len(expectedClientID), len(serverIDOption))
|
||||||
}
|
}
|
||||||
|
|
||||||
bootfileUrlOption := msg.Options.BootfileUrl()
|
bootfileURLOption := msg.Options.BootFileURL()
|
||||||
if bootfileUrlOption == nil {
|
if bootfileURLOption == nil {
|
||||||
t.Fatalf("Bootfile URL option should be present")
|
t.Fatalf("Bootfile URL option should be present")
|
||||||
}
|
}
|
||||||
if string(expectedBootFileUrl) != string(bootfileUrlOption) {
|
if string(expectedBootFileURL) != string(bootfileURLOption) {
|
||||||
t.Fatalf("Expected bootfile URL %v, got %v", expectedBootFileUrl, bootfileUrlOption)
|
t.Fatalf("Expected bootfile URL %v, got %v", expectedBootFileURL, bootfileURLOption)
|
||||||
}
|
}
|
||||||
|
|
||||||
iaNaOption := msg.Options[OptIaNa]
|
iaNaOption := msg.Options[OptIaNa]
|
||||||
@ -236,73 +236,73 @@ func TestMakeMsgReply(t *testing.T) {
|
|||||||
t.Fatalf("interface non-temporary association option should be present")
|
t.Fatalf("interface non-temporary association option should be present")
|
||||||
}
|
}
|
||||||
|
|
||||||
dnsServersOption := msg.Options[OptRecursiveDns]
|
dnsServersOption := msg.Options[OptRecursiveDNS]
|
||||||
if dnsServersOption == nil {
|
if dnsServersOption == nil {
|
||||||
t.Fatalf("DNS servers option should be set")
|
t.Fatalf("DNS servers option should be set")
|
||||||
}
|
}
|
||||||
if string(dnsServersOption[0].Value) != string(expectedDnsServerIp) {
|
if string(dnsServersOption[0].Value) != string(expectedDnsServerIP) {
|
||||||
t.Fatalf("Expected dns server %v, got %v", expectedDnsServerIp, net.IP(dnsServersOption[0].Value))
|
t.Fatalf("Expected dns server %v, got %v", expectedDnsServerIP, net.IP(dnsServersOption[0].Value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMakeMsgReplyShouldSkipDnsServersIfNoneWereConfigured(t *testing.T) {
|
func TestMakeMsgReplyShouldSkipDnsServersIfNoneWereConfigured(t *testing.T) {
|
||||||
expectedClientId := []byte("clientid")
|
expectedClientID := []byte("clientid")
|
||||||
expectedServerId := []byte("serverid")
|
expectedServerID := []byte("serverid")
|
||||||
transactionId := [3]byte{'1', '2', '3'}
|
transactionID := [3]byte{'1', '2', '3'}
|
||||||
expectedIp := net.ParseIP("2001:db8:f00f:cafe::1")
|
expectedIP := net.ParseIP("2001:db8:f00f:cafe::1")
|
||||||
expectedBootFileUrl := []byte("http://bootfileurl")
|
expectedBootFileURL := []byte("http://bootfileurl")
|
||||||
identityAssociation := &IdentityAssociation{IpAddress: expectedIp, InterfaceId: []byte("id-1")}
|
identityAssociation := &IdentityAssociation{IPAddress: expectedIP, InterfaceID: []byte("id-1")}
|
||||||
|
|
||||||
builder := MakePacketBuilder(90, 100)
|
builder := MakePacketBuilder(90, 100)
|
||||||
|
|
||||||
msg := builder.MakeMsgReply(transactionId, expectedServerId, expectedClientId, 0x11,
|
msg := builder.MakeMsgReply(transactionID, expectedServerID, expectedClientID, 0x11,
|
||||||
[]*IdentityAssociation{identityAssociation}, make([][]byte, 0), expectedBootFileUrl, []net.IP{}, nil)
|
[]*IdentityAssociation{identityAssociation}, make([][]byte, 0), expectedBootFileURL, []net.IP{}, nil)
|
||||||
|
|
||||||
_, exists := msg.Options[OptRecursiveDns]; if exists {
|
_, exists := msg.Options[OptRecursiveDNS]; if exists {
|
||||||
t.Fatalf("Dns servers option shouldn't be present")
|
t.Fatalf("Dns servers option shouldn't be present")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMakeMsgReplyWithHttpClientArch(t *testing.T) {
|
func TestMakeMsgReplyWithHttpClientArch(t *testing.T) {
|
||||||
expectedClientId := []byte("clientid")
|
expectedClientID := []byte("clientid")
|
||||||
expectedServerId := []byte("serverid")
|
expectedServerID := []byte("serverid")
|
||||||
transactionId := [3]byte{'1', '2', '3'}
|
transactionID := [3]byte{'1', '2', '3'}
|
||||||
expectedIp := net.ParseIP("2001:db8:f00f:cafe::1")
|
expectedIP := net.ParseIP("2001:db8:f00f:cafe::1")
|
||||||
expectedBootFileUrl := []byte("http://bootfileurl")
|
expectedBootFileURL := []byte("http://bootfileurl")
|
||||||
identityAssociation := &IdentityAssociation{IpAddress: expectedIp, InterfaceId: []byte("id-1")}
|
identityAssociation := &IdentityAssociation{IPAddress: expectedIP, InterfaceID: []byte("id-1")}
|
||||||
|
|
||||||
builder := MakePacketBuilder(90, 100)
|
builder := MakePacketBuilder(90, 100)
|
||||||
|
|
||||||
msg := builder.MakeMsgReply(transactionId, expectedServerId, expectedClientId, 0x10,
|
msg := builder.MakeMsgReply(transactionID, expectedServerID, expectedClientID, 0x10,
|
||||||
[]*IdentityAssociation{identityAssociation}, make([][]byte, 0), expectedBootFileUrl, []net.IP{}, nil)
|
[]*IdentityAssociation{identityAssociation}, make([][]byte, 0), expectedBootFileURL, []net.IP{}, nil)
|
||||||
|
|
||||||
vendorClassOption := msg.Options[OptVendorClass]
|
vendorClassOption := msg.Options[OptVendorClass]
|
||||||
if vendorClassOption == nil {
|
if vendorClassOption == nil {
|
||||||
t.Fatalf("Vendor class option should be present")
|
t.Fatalf("Vendor class option should be present")
|
||||||
}
|
}
|
||||||
|
|
||||||
bootfileUrlOption := msg.Options.BootfileUrl()
|
bootfileURLOption := msg.Options.BootFileURL()
|
||||||
if bootfileUrlOption == nil {
|
if bootfileURLOption == nil {
|
||||||
t.Fatalf("Bootfile URL option should be present")
|
t.Fatalf("Bootfile URL option should be present")
|
||||||
}
|
}
|
||||||
if string(expectedBootFileUrl) != string(bootfileUrlOption) {
|
if string(expectedBootFileURL) != string(bootfileURLOption) {
|
||||||
t.Fatalf("Expected bootfile URL %v, got %v", expectedBootFileUrl, bootfileUrlOption)
|
t.Fatalf("Expected bootfile URL %v, got %v", expectedBootFileURL, bootfileURLOption)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMakeMsgReplyWithNoAddrsAvailable(t *testing.T) {
|
func TestMakeMsgReplyWithNoAddrsAvailable(t *testing.T) {
|
||||||
expectedClientId := []byte("clientid")
|
expectedClientID := []byte("clientid")
|
||||||
expectedServerId := []byte("serverid")
|
expectedServerID := []byte("serverid")
|
||||||
transactionId := [3]byte{'1', '2', '3'}
|
transactionID := [3]byte{'1', '2', '3'}
|
||||||
expectedIp := net.ParseIP("2001:db8:f00f:cafe::1")
|
expectedIP := net.ParseIP("2001:db8:f00f:cafe::1")
|
||||||
expectedBootFileUrl := []byte("http://bootfileurl")
|
expectedBootFileURL := []byte("http://bootfileurl")
|
||||||
identityAssociation := &IdentityAssociation{IpAddress: expectedIp, InterfaceId: []byte("id-1")}
|
identityAssociation := &IdentityAssociation{IPAddress: expectedIP, InterfaceID: []byte("id-1")}
|
||||||
expectedErrorMessage := "Boom!"
|
expectedErrorMessage := "Boom!"
|
||||||
|
|
||||||
builder := MakePacketBuilder(90, 100)
|
builder := MakePacketBuilder(90, 100)
|
||||||
|
|
||||||
msg := builder.MakeMsgReply(transactionId, expectedServerId, expectedClientId, 0x10,
|
msg := builder.MakeMsgReply(transactionID, expectedServerID, expectedClientID, 0x10,
|
||||||
[]*IdentityAssociation{identityAssociation}, [][]byte{[]byte("id-2")}, expectedBootFileUrl, []net.IP{},
|
[]*IdentityAssociation{identityAssociation}, [][]byte{[]byte("id-2")}, expectedBootFileURL, []net.IP{},
|
||||||
fmt.Errorf(expectedErrorMessage))
|
fmt.Errorf(expectedErrorMessage))
|
||||||
|
|
||||||
iaNaOption := msg.Options[OptIaNa]
|
iaNaOption := msg.Options[OptIaNa]
|
||||||
@ -325,16 +325,16 @@ func TestMakeMsgReplyWithNoAddrsAvailable(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to unmarshal IaNa options: %s", err)
|
t.Fatalf("Failed to unmarshal IaNa options: %s", err)
|
||||||
}
|
}
|
||||||
if possiblyIaAddrOption.Id != OptIaAddr {
|
if possiblyIaAddrOption.ID != OptIaAddr {
|
||||||
t.Fatalf("Expected option 5 (ia address), got %d", possiblyIaAddrOption.Id)
|
t.Fatalf("Expected option 5 (ia address), got %d", possiblyIaAddrOption.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
possiblyStatusOption, err := UnmarshalOption(failedIaNaOption[12:])
|
possiblyStatusOption, err := UnmarshalOption(failedIaNaOption[12:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to unmarshal IaNa options: %s", err)
|
t.Fatalf("Failed to unmarshal IaNa options: %s", err)
|
||||||
}
|
}
|
||||||
if possiblyStatusOption.Id != OptStatusCode {
|
if possiblyStatusOption.ID != OptStatusCode {
|
||||||
t.Fatalf("Expected option 13 (status code), got %d", possiblyStatusOption.Id)
|
t.Fatalf("Expected option 13 (status code), got %d", possiblyStatusOption.ID)
|
||||||
}
|
}
|
||||||
if binary.BigEndian.Uint16(possiblyStatusOption.Value[0:2]) != uint16(2) {
|
if binary.BigEndian.Uint16(possiblyStatusOption.Value[0:2]) != uint16(2) {
|
||||||
t.Fatalf("Expected status code 2, got %d", binary.BigEndian.Uint16(possiblyStatusOption.Value[0:2]))
|
t.Fatalf("Expected status code 2, got %d", binary.BigEndian.Uint16(possiblyStatusOption.Value[0:2]))
|
||||||
@ -345,147 +345,147 @@ func TestMakeMsgReplyWithNoAddrsAvailable(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestMakeMsgInformationRequestReply(t *testing.T) {
|
func TestMakeMsgInformationRequestReply(t *testing.T) {
|
||||||
expectedClientId := []byte("clientid")
|
expectedClientID := []byte("clientid")
|
||||||
expectedServerId := []byte("serverid")
|
expectedServerID := []byte("serverid")
|
||||||
transactionId := [3]byte{'1', '2', '3'}
|
transactionID := [3]byte{'1', '2', '3'}
|
||||||
expectedBootFileUrl := []byte("http://bootfileurl")
|
expectedBootFileURL := []byte("http://bootfileurl")
|
||||||
expectedDnsServerIp := net.ParseIP("2001:db8:f00f:cafe::99")
|
expectedDnsServerIP := net.ParseIP("2001:db8:f00f:cafe::99")
|
||||||
|
|
||||||
builder := MakePacketBuilder(90, 100)
|
builder := MakePacketBuilder(90, 100)
|
||||||
|
|
||||||
msg := builder.MakeMsgInformationRequestReply(transactionId, expectedServerId, expectedClientId, 0x11,
|
msg := builder.MakeMsgInformationRequestReply(transactionID, expectedServerID, expectedClientID, 0x11,
|
||||||
expectedBootFileUrl, []net.IP{expectedDnsServerIp})
|
expectedBootFileURL, []net.IP{expectedDnsServerIP})
|
||||||
|
|
||||||
if msg.Type != MsgReply {
|
if msg.Type != MsgReply {
|
||||||
t.Fatalf("Expected message type %d, got %d", MsgAdvertise, msg.Type)
|
t.Fatalf("Expected message type %d, got %d", MsgAdvertise, msg.Type)
|
||||||
}
|
}
|
||||||
if transactionId != msg.TransactionID {
|
if transactionID != msg.TransactionID {
|
||||||
t.Fatalf("Expected transaction Id %v, got %v", transactionId, msg.TransactionID)
|
t.Fatalf("Expected transaction ID %v, got %v", transactionID, msg.TransactionID)
|
||||||
}
|
}
|
||||||
|
|
||||||
clientIdOption := msg.Options.ClientId()
|
clientIDOption := msg.Options.ClientID()
|
||||||
if clientIdOption == nil {
|
if clientIDOption == nil {
|
||||||
t.Fatalf("Client Id option should be present")
|
t.Fatalf("Client ID option should be present")
|
||||||
}
|
}
|
||||||
if string(expectedClientId) != string(clientIdOption) {
|
if string(expectedClientID) != string(clientIDOption) {
|
||||||
t.Fatalf("Expected client id %v, got %v", expectedClientId, clientIdOption)
|
t.Fatalf("Expected Client id %v, got %v", expectedClientID, clientIDOption)
|
||||||
}
|
}
|
||||||
if len(expectedClientId) != len(clientIdOption) {
|
if len(expectedClientID) != len(clientIDOption) {
|
||||||
t.Fatalf("Expected client id length of %d, got %d", len(expectedClientId), len(clientIdOption))
|
t.Fatalf("Expected Client id length of %d, got %d", len(expectedClientID), len(clientIDOption))
|
||||||
}
|
}
|
||||||
|
|
||||||
serverIdOption := msg.Options.ServerId()
|
serverIDOption := msg.Options.ServerID()
|
||||||
if serverIdOption == nil {
|
if serverIDOption == nil {
|
||||||
t.Fatalf("Server Id option should be present")
|
t.Fatalf("Server ID option should be present")
|
||||||
}
|
}
|
||||||
if string(expectedServerId) != string(serverIdOption) {
|
if string(expectedServerID) != string(serverIDOption) {
|
||||||
t.Fatalf("Expected server id %v, got %v", expectedClientId, serverIdOption)
|
t.Fatalf("Expected server id %v, got %v", expectedClientID, serverIDOption)
|
||||||
}
|
}
|
||||||
if len(expectedServerId) != len(serverIdOption) {
|
if len(expectedServerID) != len(serverIDOption) {
|
||||||
t.Fatalf("Expected server id length of %d, got %d", len(expectedClientId), len(serverIdOption))
|
t.Fatalf("Expected server id length of %d, got %d", len(expectedClientID), len(serverIDOption))
|
||||||
}
|
}
|
||||||
|
|
||||||
bootfileUrlOption := msg.Options.BootfileUrl()
|
bootfileURLOption := msg.Options.BootFileURL()
|
||||||
if bootfileUrlOption == nil {
|
if bootfileURLOption == nil {
|
||||||
t.Fatalf("Bootfile URL option should be present")
|
t.Fatalf("Bootfile URL option should be present")
|
||||||
}
|
}
|
||||||
if string(expectedBootFileUrl) != string(bootfileUrlOption) {
|
if string(expectedBootFileURL) != string(bootfileURLOption) {
|
||||||
t.Fatalf("Expected bootfile URL %v, got %v", expectedBootFileUrl, bootfileUrlOption)
|
t.Fatalf("Expected bootfile URL %v, got %v", expectedBootFileURL, bootfileURLOption)
|
||||||
}
|
}
|
||||||
|
|
||||||
dnsServersOption := msg.Options[OptRecursiveDns]
|
dnsServersOption := msg.Options[OptRecursiveDNS]
|
||||||
if dnsServersOption == nil {
|
if dnsServersOption == nil {
|
||||||
t.Fatalf("DNS servers option should be set")
|
t.Fatalf("DNS servers option should be set")
|
||||||
}
|
}
|
||||||
if string(dnsServersOption[0].Value) != string(expectedDnsServerIp) {
|
if string(dnsServersOption[0].Value) != string(expectedDnsServerIP) {
|
||||||
t.Fatalf("Expected dns server %v, got %v", expectedDnsServerIp, net.IP(dnsServersOption[0].Value))
|
t.Fatalf("Expected dns server %v, got %v", expectedDnsServerIP, net.IP(dnsServersOption[0].Value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMakeMsgInformationRequestReplyShouldSkipDnsServersIfNoneWereConfigured(t *testing.T) {
|
func TestMakeMsgInformationRequestReplyShouldSkipDnsServersIfNoneWereConfigured(t *testing.T) {
|
||||||
expectedClientId := []byte("clientid")
|
expectedClientID := []byte("clientid")
|
||||||
expectedServerId := []byte("serverid")
|
expectedServerID := []byte("serverid")
|
||||||
transactionId := [3]byte{'1', '2', '3'}
|
transactionID := [3]byte{'1', '2', '3'}
|
||||||
expectedBootFileUrl := []byte("http://bootfileurl")
|
expectedBootFileURL := []byte("http://bootfileurl")
|
||||||
|
|
||||||
builder := MakePacketBuilder(90, 100)
|
builder := MakePacketBuilder(90, 100)
|
||||||
|
|
||||||
msg := builder.MakeMsgInformationRequestReply(transactionId, expectedServerId, expectedClientId, 0x11,
|
msg := builder.MakeMsgInformationRequestReply(transactionID, expectedServerID, expectedClientID, 0x11,
|
||||||
expectedBootFileUrl, []net.IP{})
|
expectedBootFileURL, []net.IP{})
|
||||||
|
|
||||||
_, exists := msg.Options[OptRecursiveDns]; if exists {
|
_, exists := msg.Options[OptRecursiveDNS]; if exists {
|
||||||
t.Fatalf("Dns servers option shouldn't be present")
|
t.Fatalf("Dns servers option shouldn't be present")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMakeMsgInformationRequestReplyWithHttpClientArch(t *testing.T) {
|
func TestMakeMsgInformationRequestReplyWithHttpClientArch(t *testing.T) {
|
||||||
expectedClientId := []byte("clientid")
|
expectedClientID := []byte("clientid")
|
||||||
expectedServerId := []byte("serverid")
|
expectedServerID := []byte("serverid")
|
||||||
transactionId := [3]byte{'1', '2', '3'}
|
transactionID := [3]byte{'1', '2', '3'}
|
||||||
expectedBootFileUrl := []byte("http://bootfileurl")
|
expectedBootFileURL := []byte("http://bootfileurl")
|
||||||
|
|
||||||
builder := MakePacketBuilder(90, 100)
|
builder := MakePacketBuilder(90, 100)
|
||||||
|
|
||||||
msg := builder.MakeMsgInformationRequestReply(transactionId, expectedServerId, expectedClientId, 0x10,
|
msg := builder.MakeMsgInformationRequestReply(transactionID, expectedServerID, expectedClientID, 0x10,
|
||||||
expectedBootFileUrl, []net.IP{})
|
expectedBootFileURL, []net.IP{})
|
||||||
|
|
||||||
vendorClassOption := msg.Options[OptVendorClass]
|
vendorClassOption := msg.Options[OptVendorClass]
|
||||||
if vendorClassOption == nil {
|
if vendorClassOption == nil {
|
||||||
t.Fatalf("Vendor class option should be present")
|
t.Fatalf("Vendor class option should be present")
|
||||||
}
|
}
|
||||||
|
|
||||||
bootfileUrlOption := msg.Options.BootfileUrl()
|
bootfileURLOption := msg.Options.BootFileURL()
|
||||||
if bootfileUrlOption == nil {
|
if bootfileURLOption == nil {
|
||||||
t.Fatalf("Bootfile URL option should be present")
|
t.Fatalf("Bootfile URL option should be present")
|
||||||
}
|
}
|
||||||
if string(expectedBootFileUrl) != string(bootfileUrlOption) {
|
if string(expectedBootFileURL) != string(bootfileURLOption) {
|
||||||
t.Fatalf("Expected bootfile URL %v, got %v", expectedBootFileUrl, bootfileUrlOption)
|
t.Fatalf("Expected bootfile URL %v, got %v", expectedBootFileURL, bootfileURLOption)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMakeMsgReleaseReply(t *testing.T) {
|
func TestMakeMsgReleaseReply(t *testing.T) {
|
||||||
expectedClientId := []byte("clientid")
|
expectedClientID := []byte("clientid")
|
||||||
expectedServerId := []byte("serverid")
|
expectedServerID := []byte("serverid")
|
||||||
transactionId := [3]byte{'1', '2', '3'}
|
transactionID := [3]byte{'1', '2', '3'}
|
||||||
|
|
||||||
builder := MakePacketBuilder(90, 100)
|
builder := MakePacketBuilder(90, 100)
|
||||||
|
|
||||||
msg := builder.MakeMsgReleaseReply(transactionId, expectedServerId, expectedClientId)
|
msg := builder.MakeMsgReleaseReply(transactionID, expectedServerID, expectedClientID)
|
||||||
|
|
||||||
if msg.Type != MsgReply {
|
if msg.Type != MsgReply {
|
||||||
t.Fatalf("Expected message type %d, got %d", MsgAdvertise, msg.Type)
|
t.Fatalf("Expected message type %d, got %d", MsgAdvertise, msg.Type)
|
||||||
}
|
}
|
||||||
if transactionId != msg.TransactionID {
|
if transactionID != msg.TransactionID {
|
||||||
t.Fatalf("Expected transaction Id %v, got %v", transactionId, msg.TransactionID)
|
t.Fatalf("Expected transaction ID %v, got %v", transactionID, msg.TransactionID)
|
||||||
}
|
}
|
||||||
|
|
||||||
clientIdOption := msg.Options.ClientId()
|
clientIDOption := msg.Options.ClientID()
|
||||||
if clientIdOption == nil {
|
if clientIDOption == nil {
|
||||||
t.Fatalf("Client Id option should be present")
|
t.Fatalf("Client ID option should be present")
|
||||||
}
|
}
|
||||||
if string(expectedClientId) != string(clientIdOption) {
|
if string(expectedClientID) != string(clientIDOption) {
|
||||||
t.Fatalf("Expected client id %v, got %v", expectedClientId, clientIdOption)
|
t.Fatalf("Expected Client id %v, got %v", expectedClientID, clientIDOption)
|
||||||
}
|
}
|
||||||
if len(expectedClientId) != len(clientIdOption) {
|
if len(expectedClientID) != len(clientIDOption) {
|
||||||
t.Fatalf("Expected client id length of %d, got %d", len(expectedClientId), len(clientIdOption))
|
t.Fatalf("Expected Client id length of %d, got %d", len(expectedClientID), len(clientIDOption))
|
||||||
}
|
}
|
||||||
|
|
||||||
serverIdOption := msg.Options.ServerId()
|
serverIDOption := msg.Options.ServerID()
|
||||||
if serverIdOption == nil {
|
if serverIDOption == nil {
|
||||||
t.Fatalf("Server Id option should be present")
|
t.Fatalf("Server ID option should be present")
|
||||||
}
|
}
|
||||||
if string(expectedServerId) != string(serverIdOption) {
|
if string(expectedServerID) != string(serverIDOption) {
|
||||||
t.Fatalf("Expected server id %v, got %v", expectedClientId, serverIdOption)
|
t.Fatalf("Expected server id %v, got %v", expectedClientID, serverIDOption)
|
||||||
}
|
}
|
||||||
if len(expectedServerId) != len(serverIdOption) {
|
if len(expectedServerID) != len(serverIDOption) {
|
||||||
t.Fatalf("Expected server id length of %d, got %d", len(expectedClientId), len(serverIdOption))
|
t.Fatalf("Expected server id length of %d, got %d", len(expectedClientID), len(serverIDOption))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExtractLLAddressOrIdWithDUIDLLT(t *testing.T) {
|
func TestExtractLLAddressOrIdWithDUIDLLT(t *testing.T) {
|
||||||
builder := &PacketBuilder{}
|
builder := &PacketBuilder{}
|
||||||
expectedLLAddress := []byte{0xac, 0xbc, 0x32, 0xae, 0x86, 0x37}
|
expectedLLAddress := []byte{0xac, 0xbc, 0x32, 0xae, 0x86, 0x37}
|
||||||
llAddress := builder.ExtractLLAddressOrId([]byte{0x0, 0x1, 0x0, 0x1, 0x1, 0x2, 0x3, 0x4, 0xac, 0xbc, 0x32, 0xae, 0x86, 0x37})
|
llAddress := builder.ExtractLLAddressOrID([]byte{0x0, 0x1, 0x0, 0x1, 0x1, 0x2, 0x3, 0x4, 0xac, 0xbc, 0x32, 0xae, 0x86, 0x37})
|
||||||
if string(expectedLLAddress) != string(llAddress) {
|
if string(expectedLLAddress) != string(llAddress) {
|
||||||
t.Fatalf("Expected ll address %x, got: %x", expectedLLAddress, llAddress)
|
t.Fatalf("Expected ll address %x, got: %x", expectedLLAddress, llAddress)
|
||||||
}
|
}
|
||||||
@ -494,7 +494,7 @@ func TestExtractLLAddressOrIdWithDUIDLLT(t *testing.T) {
|
|||||||
func TestExtractLLAddressOrIdWithDUIDEN(t *testing.T) {
|
func TestExtractLLAddressOrIdWithDUIDEN(t *testing.T) {
|
||||||
builder := &PacketBuilder{}
|
builder := &PacketBuilder{}
|
||||||
expectedId := []byte{0x0, 0x1, 0x2, 0x3, 0xac, 0xbc, 0x32, 0xae, 0x86, 0x37}
|
expectedId := []byte{0x0, 0x1, 0x2, 0x3, 0xac, 0xbc, 0x32, 0xae, 0x86, 0x37}
|
||||||
id := builder.ExtractLLAddressOrId([]byte{0x0, 0x2, 0x0, 0x1, 0x2, 0x3, 0xac, 0xbc, 0x32, 0xae, 0x86, 0x37})
|
id := builder.ExtractLLAddressOrID([]byte{0x0, 0x2, 0x0, 0x1, 0x2, 0x3, 0xac, 0xbc, 0x32, 0xae, 0x86, 0x37})
|
||||||
if string(expectedId) != string(id) {
|
if string(expectedId) != string(id) {
|
||||||
t.Fatalf("Expected id %x, got: %x", expectedId, id)
|
t.Fatalf("Expected id %x, got: %x", expectedId, id)
|
||||||
}
|
}
|
||||||
@ -503,7 +503,7 @@ func TestExtractLLAddressOrIdWithDUIDEN(t *testing.T) {
|
|||||||
func TestExtractLLAddressOrIdWithDUIDLL(t *testing.T) {
|
func TestExtractLLAddressOrIdWithDUIDLL(t *testing.T) {
|
||||||
builder := &PacketBuilder{}
|
builder := &PacketBuilder{}
|
||||||
expectedLLAddress := []byte{0xac, 0xbc, 0x32, 0xae, 0x86, 0x37}
|
expectedLLAddress := []byte{0xac, 0xbc, 0x32, 0xae, 0x86, 0x37}
|
||||||
llAddress := builder.ExtractLLAddressOrId([]byte{0x0, 0x3, 0x0, 0x1, 0xac, 0xbc, 0x32, 0xae, 0x86, 0x37})
|
llAddress := builder.ExtractLLAddressOrID([]byte{0x0, 0x3, 0x0, 0x1, 0xac, 0xbc, 0x32, 0xae, 0x86, 0x37})
|
||||||
if string(expectedLLAddress) != string(llAddress) {
|
if string(expectedLLAddress) != string(llAddress) {
|
||||||
t.Fatalf("Expected ll address %x, got: %x", expectedLLAddress, llAddress)
|
t.Fatalf("Expected ll address %x, got: %x", expectedLLAddress, llAddress)
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestShouldDiscardSolicitWithoutBootfileUrlOption(t *testing.T) {
|
func TestShouldDiscardSolicitWithoutBootfileUrlOption(t *testing.T) {
|
||||||
clientId := []byte("clientid")
|
clientID := []byte("clientid")
|
||||||
options := make(Options)
|
options := make(Options)
|
||||||
options.AddOption(&Option{Id: OptClientId, Length: uint16(len(clientId)), Value: clientId})
|
options.AddOption(&Option{ID: OptClientID, Length: uint16(len(clientID)), Value: clientID})
|
||||||
solicit := &Packet{Type: MsgSolicit, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
solicit := &Packet{Type: MsgSolicit, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
||||||
|
|
||||||
if err := ShouldDiscardSolicit(solicit); err == nil {
|
if err := ShouldDiscardSolicit(solicit); err == nil {
|
||||||
@ -18,7 +18,7 @@ func TestShouldDiscardSolicitWithoutBootfileUrlOption(t *testing.T) {
|
|||||||
|
|
||||||
func TestShouldDiscardSolicitWithoutClientIdOption(t *testing.T) {
|
func TestShouldDiscardSolicitWithoutClientIdOption(t *testing.T) {
|
||||||
options := make(Options)
|
options := make(Options)
|
||||||
options.AddOption(MakeOptionRequestOptions([]uint16{OptBootfileUrl}))
|
options.AddOption(MakeOptionRequestOptions([]uint16{OptBootfileURL}))
|
||||||
solicit := &Packet{Type: MsgSolicit, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
solicit := &Packet{Type: MsgSolicit, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
||||||
|
|
||||||
if err := ShouldDiscardSolicit(solicit); err == nil {
|
if err := ShouldDiscardSolicit(solicit); err == nil {
|
||||||
@ -27,12 +27,12 @@ func TestShouldDiscardSolicitWithoutClientIdOption(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestShouldDiscardSolicitWithServerIdOption(t *testing.T) {
|
func TestShouldDiscardSolicitWithServerIdOption(t *testing.T) {
|
||||||
serverId := []byte("serverid")
|
serverID := []byte("serverid")
|
||||||
clientId := []byte("clientid")
|
clientID := []byte("clientid")
|
||||||
options := make(Options)
|
options := make(Options)
|
||||||
options.AddOption(MakeOptionRequestOptions([]uint16{OptBootfileUrl}))
|
options.AddOption(MakeOptionRequestOptions([]uint16{OptBootfileURL}))
|
||||||
options.AddOption(&Option{Id: OptClientId, Length: uint16(len(clientId)), Value: clientId})
|
options.AddOption(&Option{ID: OptClientID, Length: uint16(len(clientID)), Value: clientID})
|
||||||
options.AddOption(&Option{Id: OptServerId, Length: uint16(len(serverId)), Value: serverId})
|
options.AddOption(&Option{ID: OptServerID, Length: uint16(len(serverID)), Value: serverID})
|
||||||
solicit := &Packet{Type: MsgSolicit, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
solicit := &Packet{Type: MsgSolicit, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
||||||
|
|
||||||
if err := ShouldDiscardSolicit(solicit); err == nil {
|
if err := ShouldDiscardSolicit(solicit); err == nil {
|
||||||
@ -41,35 +41,35 @@ func TestShouldDiscardSolicitWithServerIdOption(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestShouldDiscardRequestWithoutBootfileUrlOption(t *testing.T) {
|
func TestShouldDiscardRequestWithoutBootfileUrlOption(t *testing.T) {
|
||||||
serverId := []byte("serverid")
|
serverID := []byte("serverid")
|
||||||
clientId := []byte("clientid")
|
clientID := []byte("clientid")
|
||||||
options := make(Options)
|
options := make(Options)
|
||||||
options.AddOption(&Option{Id: OptClientId, Length: uint16(len(clientId)), Value: clientId})
|
options.AddOption(&Option{ID: OptClientID, Length: uint16(len(clientID)), Value: clientID})
|
||||||
options.AddOption(&Option{Id: OptServerId, Length: uint16(len(serverId)), Value: serverId})
|
options.AddOption(&Option{ID: OptServerID, Length: uint16(len(serverID)), Value: serverID})
|
||||||
request := &Packet{Type: MsgRequest, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
request := &Packet{Type: MsgRequest, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
||||||
|
|
||||||
if err := ShouldDiscardRequest(request, serverId); err == nil {
|
if err := ShouldDiscardRequest(request, serverID); err == nil {
|
||||||
t.Fatalf("Should discard request packet without bootfile url option, but didn't")
|
t.Fatalf("Should discard request packet without bootfile url option, but didn't")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestShouldDiscardRequestWithoutClientIdOption(t *testing.T) {
|
func TestShouldDiscardRequestWithoutClientIdOption(t *testing.T) {
|
||||||
serverId := []byte("serverid")
|
serverID := []byte("serverid")
|
||||||
options := make(Options)
|
options := make(Options)
|
||||||
options.AddOption(MakeOptionRequestOptions([]uint16{OptBootfileUrl}))
|
options.AddOption(MakeOptionRequestOptions([]uint16{OptBootfileURL}))
|
||||||
options.AddOption(&Option{Id: OptServerId, Length: uint16(len(serverId)), Value: serverId})
|
options.AddOption(&Option{ID: OptServerID, Length: uint16(len(serverID)), Value: serverID})
|
||||||
request := &Packet{Type: MsgRequest, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
request := &Packet{Type: MsgRequest, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
||||||
|
|
||||||
if err := ShouldDiscardRequest(request, serverId); err == nil {
|
if err := ShouldDiscardRequest(request, serverID); err == nil {
|
||||||
t.Fatalf("Should discard request packet without client id option, but didn't")
|
t.Fatalf("Should discard request packet without client id option, but didn't")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestShouldDiscardRequestWithoutServerIdOption(t *testing.T) {
|
func TestShouldDiscardRequestWithoutServerIdOption(t *testing.T) {
|
||||||
clientId := []byte("clientid")
|
clientID := []byte("clientid")
|
||||||
options := make(Options)
|
options := make(Options)
|
||||||
options.AddOption(MakeOptionRequestOptions([]uint16{OptBootfileUrl}))
|
options.AddOption(MakeOptionRequestOptions([]uint16{OptBootfileURL}))
|
||||||
options.AddOption(&Option{Id: OptClientId, Length: uint16(len(clientId)), Value: clientId})
|
options.AddOption(&Option{ID: OptClientID, Length: uint16(len(clientID)), Value: clientID})
|
||||||
request := &Packet{Type: MsgRequest, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
request := &Packet{Type: MsgRequest, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
||||||
|
|
||||||
if err := ShouldDiscardRequest(request, []byte("serverid")); err == nil {
|
if err := ShouldDiscardRequest(request, []byte("serverid")); err == nil {
|
||||||
@ -78,12 +78,12 @@ func TestShouldDiscardRequestWithoutServerIdOption(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestShouldDiscardRequestWithWrongServerId(t *testing.T) {
|
func TestShouldDiscardRequestWithWrongServerId(t *testing.T) {
|
||||||
clientId := []byte("clientid")
|
clientID := []byte("clientid")
|
||||||
serverId := []byte("serverid")
|
serverID := []byte("serverid")
|
||||||
options := make(Options)
|
options := make(Options)
|
||||||
options.AddOption(MakeOptionRequestOptions([]uint16{OptBootfileUrl}))
|
options.AddOption(MakeOptionRequestOptions([]uint16{OptBootfileURL}))
|
||||||
options.AddOption(&Option{Id: OptClientId, Length: uint16(len(clientId)), Value: clientId})
|
options.AddOption(&Option{ID: OptClientID, Length: uint16(len(clientID)), Value: clientID})
|
||||||
options.AddOption(&Option{Id: OptServerId, Length: uint16(len(serverId)), Value: serverId})
|
options.AddOption(&Option{ID: OptServerID, Length: uint16(len(serverID)), Value: serverID})
|
||||||
request := &Packet{Type: MsgRequest, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
request := &Packet{Type: MsgRequest, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
||||||
|
|
||||||
if err := ShouldDiscardRequest(request, []byte("wrongid")); err == nil {
|
if err := ShouldDiscardRequest(request, []byte("wrongid")); err == nil {
|
||||||
@ -97,6 +97,6 @@ func MakeOptionRequestOptions(options []uint16) *Option {
|
|||||||
binary.BigEndian.PutUint16(value[i*2:], option)
|
binary.BigEndian.PutUint16(value[i*2:], option)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Option{Id: OptOro, Length: uint16(len(options)*2), Value: value}
|
return &Option{ID: OptOro, Length: uint16(len(options)*2), Value: value}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,9 +26,9 @@ func (f *Fifo) Push(v interface{}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *Fifo) Shift() interface{} {
|
func (f *Fifo) Shift() interface{} {
|
||||||
var to_ret interface{}
|
var ret interface{}
|
||||||
to_ret, f.q = f.q[0], f.q[1:]
|
ret, f.q = f.q[0], f.q[1:]
|
||||||
return to_ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Fifo) Size() int {
|
func (f *Fifo) Size() int {
|
||||||
@ -54,37 +54,37 @@ type RandomAddressPool struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewRandomAddressPool(poolStartAddress net.IP, poolSize uint64, validLifetime uint32) *RandomAddressPool {
|
func NewRandomAddressPool(poolStartAddress net.IP, poolSize uint64, validLifetime uint32) *RandomAddressPool {
|
||||||
to_ret := &RandomAddressPool{}
|
ret := &RandomAddressPool{}
|
||||||
to_ret.validLifetime = validLifetime
|
ret.validLifetime = validLifetime
|
||||||
to_ret.poolStartAddress = big.NewInt(0)
|
ret.poolStartAddress = big.NewInt(0)
|
||||||
to_ret.poolStartAddress.SetBytes(poolStartAddress)
|
ret.poolStartAddress.SetBytes(poolStartAddress)
|
||||||
to_ret.poolSize = poolSize
|
ret.poolSize = poolSize
|
||||||
to_ret.identityAssociations = make(map[uint64]*IdentityAssociation)
|
ret.identityAssociations = make(map[uint64]*IdentityAssociation)
|
||||||
to_ret.usedIps = make(map[uint64]struct{})
|
ret.usedIps = make(map[uint64]struct{})
|
||||||
to_ret.identityAssociationExpirations = newFifo()
|
ret.identityAssociationExpirations = newFifo()
|
||||||
to_ret.timeNow = func() time.Time { return time.Now() }
|
ret.timeNow = func() time.Time { return time.Now() }
|
||||||
|
|
||||||
ticker := time.NewTicker(time.Second * 10).C
|
ticker := time.NewTicker(time.Second * 10).C
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
<- ticker
|
<- ticker
|
||||||
to_ret.ExpireIdentityAssociations()
|
ret.ExpireIdentityAssociations()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return to_ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *RandomAddressPool) ReserveAddresses(clientId []byte, interfaceIds [][]byte) ([]*IdentityAssociation, error) {
|
func (p *RandomAddressPool) ReserveAddresses(clientID []byte, interfaceIDs [][]byte) ([]*IdentityAssociation, error) {
|
||||||
p.lock.Lock()
|
p.lock.Lock()
|
||||||
defer p.lock.Unlock()
|
defer p.lock.Unlock()
|
||||||
|
|
||||||
ret := make([]*IdentityAssociation, 0, len(interfaceIds))
|
ret := make([]*IdentityAssociation, 0, len(interfaceIDs))
|
||||||
rng := rand.New(rand.NewSource(p.timeNow().UnixNano()))
|
rng := rand.New(rand.NewSource(p.timeNow().UnixNano()))
|
||||||
|
|
||||||
for _, interfaceId := range (interfaceIds) {
|
for _, interfaceID := range (interfaceIDs) {
|
||||||
clientIdHash := p.calculateIaIdHash(clientId, interfaceId)
|
clientIDHash := p.calculateIAIDHash(clientID, interfaceID)
|
||||||
association, exists := p.identityAssociations[clientIdHash];
|
association, exists := p.identityAssociations[clientIDHash];
|
||||||
|
|
||||||
if exists {
|
if exists {
|
||||||
ret = append(ret, association)
|
ret = append(ret, association)
|
||||||
@ -101,11 +101,11 @@ func (p *RandomAddressPool) ReserveAddresses(clientId []byte, interfaceIds [][]b
|
|||||||
_, exists := p.usedIps[newIp.Uint64()];
|
_, exists := p.usedIps[newIp.Uint64()];
|
||||||
if !exists {
|
if !exists {
|
||||||
timeNow := p.timeNow()
|
timeNow := p.timeNow()
|
||||||
association := &IdentityAssociation{ClientId: clientId,
|
association := &IdentityAssociation{ClientID: clientID,
|
||||||
InterfaceId: interfaceId,
|
InterfaceID: interfaceID,
|
||||||
IpAddress: newIp.Bytes(),
|
IPAddress: newIp.Bytes(),
|
||||||
CreatedAt: timeNow}
|
CreatedAt: timeNow}
|
||||||
p.identityAssociations[clientIdHash] = association
|
p.identityAssociations[clientIDHash] = association
|
||||||
p.usedIps[newIp.Uint64()] = struct{}{}
|
p.usedIps[newIp.Uint64()] = struct{}{}
|
||||||
p.identityAssociationExpirations.Push(&AssociationExpiration{expiresAt: p.calculateAssociationExpiration(timeNow), ia: association})
|
p.identityAssociationExpirations.Push(&AssociationExpiration{expiresAt: p.calculateAssociationExpiration(timeNow), ia: association})
|
||||||
ret = append(ret, association)
|
ret = append(ret, association)
|
||||||
@ -117,17 +117,17 @@ func (p *RandomAddressPool) ReserveAddresses(clientId []byte, interfaceIds [][]b
|
|||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *RandomAddressPool) ReleaseAddresses(clientId []byte, interfaceIds [][]byte) {
|
func (p *RandomAddressPool) ReleaseAddresses(clientID []byte, interfaceIDs [][]byte) {
|
||||||
p.lock.Lock()
|
p.lock.Lock()
|
||||||
defer p.lock.Unlock()
|
defer p.lock.Unlock()
|
||||||
|
|
||||||
for _, interfaceId := range(interfaceIds) {
|
for _, interfaceId := range(interfaceIDs) {
|
||||||
association, exists := p.identityAssociations[p.calculateIaIdHash(clientId, interfaceId)]
|
association, exists := p.identityAssociations[p.calculateIAIDHash(clientID, interfaceId)]
|
||||||
if !exists {
|
if !exists {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
delete(p.usedIps, big.NewInt(0).SetBytes(association.IpAddress).Uint64())
|
delete(p.usedIps, big.NewInt(0).SetBytes(association.IPAddress).Uint64())
|
||||||
delete(p.identityAssociations, p.calculateIaIdHash(clientId, interfaceId))
|
delete(p.identityAssociations, p.calculateIAIDHash(clientID, interfaceId))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,8 +140,8 @@ func (p *RandomAddressPool) ExpireIdentityAssociations() {
|
|||||||
expiration := p.identityAssociationExpirations.Peek().(*AssociationExpiration)
|
expiration := p.identityAssociationExpirations.Peek().(*AssociationExpiration)
|
||||||
if p.timeNow().Before(expiration.expiresAt) { break }
|
if p.timeNow().Before(expiration.expiresAt) { break }
|
||||||
p.identityAssociationExpirations.Shift()
|
p.identityAssociationExpirations.Shift()
|
||||||
delete(p.identityAssociations, p.calculateIaIdHash(expiration.ia.ClientId, expiration.ia.InterfaceId))
|
delete(p.identityAssociations, p.calculateIAIDHash(expiration.ia.ClientID, expiration.ia.InterfaceID))
|
||||||
delete(p.usedIps, big.NewInt(0).SetBytes(expiration.ia.IpAddress).Uint64())
|
delete(p.usedIps, big.NewInt(0).SetBytes(expiration.ia.IPAddress).Uint64())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,10 +149,10 @@ func (p *RandomAddressPool) calculateAssociationExpiration(now time.Time) time.T
|
|||||||
return now.Add(time.Duration(p.validLifetime)*time.Second)
|
return now.Add(time.Duration(p.validLifetime)*time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *RandomAddressPool) calculateIaIdHash(clientId, interfaceId []byte) uint64 {
|
func (p *RandomAddressPool) calculateIAIDHash(clientID, interfaceID []byte) uint64 {
|
||||||
h := fnv.New64a()
|
h := fnv.New64a()
|
||||||
h.Write(clientId)
|
h.Write(clientID)
|
||||||
h.Write(interfaceId)
|
h.Write(interfaceID)
|
||||||
return h.Sum64()
|
return h.Sum64()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,42 +7,42 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestReserveAddress(t *testing.T) {
|
func TestReserveAddress(t *testing.T) {
|
||||||
expectedIp1 := net.ParseIP("2001:db8:f00f:cafe::1")
|
expectedIP1 := net.ParseIP("2001:db8:f00f:cafe::1")
|
||||||
expectedIp2 := net.ParseIP("2001:db8:f00f:cafe::2")
|
expectedIP2 := net.ParseIP("2001:db8:f00f:cafe::2")
|
||||||
expectedClientId := []byte("client-id")
|
expectedClientID := []byte("Client-id")
|
||||||
expectedIaId1 := []byte("interface-id-1")
|
expectedIAID1 := []byte("interface-id-1")
|
||||||
expectedIaId2 := []byte("interface-id-2")
|
expectedIAID2 := []byte("interface-id-2")
|
||||||
expectedTime := time.Now()
|
expectedTime := time.Now()
|
||||||
expectedMaxLifetime := uint32(100)
|
expectedMaxLifetime := uint32(100)
|
||||||
|
|
||||||
pool := NewRandomAddressPool(expectedIp1, 2, expectedMaxLifetime)
|
pool := NewRandomAddressPool(expectedIP1, 2, expectedMaxLifetime)
|
||||||
pool.timeNow = func() time.Time { return expectedTime }
|
pool.timeNow = func() time.Time { return expectedTime }
|
||||||
ias, _ := pool.ReserveAddresses(expectedClientId, [][]byte{expectedIaId1, expectedIaId2})
|
ias, _ := pool.ReserveAddresses(expectedClientID, [][]byte{expectedIAID1, expectedIAID2})
|
||||||
|
|
||||||
if len(ias) != 2 {
|
if len(ias) != 2 {
|
||||||
t.Fatalf("Expected 2 identity associations but received %d", len(ias))
|
t.Fatalf("Expected 2 identity associations but received %d", len(ias))
|
||||||
}
|
}
|
||||||
if string(ias[0].IpAddress) != string(expectedIp1) && string(ias[0].IpAddress) != string(expectedIp2) {
|
if string(ias[0].IPAddress) != string(expectedIP1) && string(ias[0].IPAddress) != string(expectedIP2) {
|
||||||
t.Fatalf("Unexpected ip address: %v", ias[0].IpAddress)
|
t.Fatalf("Unexpected ip address: %v", ias[0].IPAddress)
|
||||||
}
|
}
|
||||||
if string(ias[0].ClientId) != string(expectedClientId) {
|
if string(ias[0].ClientID) != string(expectedClientID) {
|
||||||
t.Fatalf("Expected client id: %v, but got: %v", expectedClientId, ias[0].ClientId)
|
t.Fatalf("Expected Client id: %v, but got: %v", expectedClientID, ias[0].ClientID)
|
||||||
}
|
}
|
||||||
if string(ias[0].InterfaceId) != string(expectedIaId1) {
|
if string(ias[0].InterfaceID) != string(expectedIAID1) {
|
||||||
t.Fatalf("Expected interface id: %v, but got: %v", expectedIaId1, ias[0].InterfaceId)
|
t.Fatalf("Expected interface id: %v, but got: %v", expectedIAID1, ias[0].InterfaceID)
|
||||||
}
|
}
|
||||||
if ias[0].CreatedAt != expectedTime {
|
if ias[0].CreatedAt != expectedTime {
|
||||||
t.Fatalf("Expected creation time: %v, but got: %v", expectedTime, ias[0].CreatedAt)
|
t.Fatalf("Expected creation time: %v, but got: %v", expectedTime, ias[0].CreatedAt)
|
||||||
}
|
}
|
||||||
|
|
||||||
if string(ias[1].IpAddress) != string(expectedIp1) && string(ias[1].IpAddress) != string(expectedIp2) {
|
if string(ias[1].IPAddress) != string(expectedIP1) && string(ias[1].IPAddress) != string(expectedIP2) {
|
||||||
t.Fatalf("Unexpected ip address: %v", ias[0].IpAddress)
|
t.Fatalf("Unexpected ip address: %v", ias[0].IPAddress)
|
||||||
}
|
}
|
||||||
if string(ias[1].ClientId) != string(expectedClientId) {
|
if string(ias[1].ClientID) != string(expectedClientID) {
|
||||||
t.Fatalf("Expected client id: %v, but got: %v", expectedClientId, ias[1].ClientId)
|
t.Fatalf("Expected Client id: %v, but got: %v", expectedClientID, ias[1].ClientID)
|
||||||
}
|
}
|
||||||
if string(ias[1].InterfaceId) != string(expectedIaId2) {
|
if string(ias[1].InterfaceID) != string(expectedIAID2) {
|
||||||
t.Fatalf("Expected interface id: %v, but got: %v", expectedIaId2, ias[1].InterfaceId)
|
t.Fatalf("Expected interface id: %v, but got: %v", expectedIAID2, ias[1].InterfaceID)
|
||||||
}
|
}
|
||||||
if ias[1].CreatedAt != expectedTime {
|
if ias[1].CreatedAt != expectedTime {
|
||||||
t.Fatalf("Expected creation time: %v, but got: %v", expectedTime, ias[1].CreatedAt)
|
t.Fatalf("Expected creation time: %v, but got: %v", expectedTime, ias[1].CreatedAt)
|
||||||
@ -50,35 +50,35 @@ func TestReserveAddress(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestReserveAddressUpdatesAddressPool(t *testing.T) {
|
func TestReserveAddressUpdatesAddressPool(t *testing.T) {
|
||||||
expectedClientId := []byte("client-id")
|
expectedClientID := []byte("Client-id")
|
||||||
expectedIaId := []byte("interface-id")
|
expectedIAID := []byte("interface-id")
|
||||||
expectedTime := time.Now()
|
expectedTime := time.Now()
|
||||||
expectedMaxLifetime := uint32(100)
|
expectedMaxLifetime := uint32(100)
|
||||||
|
|
||||||
pool := NewRandomAddressPool(net.ParseIP("2001:db8:f00f:cafe::1"), 1, expectedMaxLifetime)
|
pool := NewRandomAddressPool(net.ParseIP("2001:db8:f00f:cafe::1"), 1, expectedMaxLifetime)
|
||||||
pool.timeNow = func() time.Time { return expectedTime }
|
pool.timeNow = func() time.Time { return expectedTime }
|
||||||
pool.ReserveAddresses(expectedClientId, [][]byte{expectedIaId})
|
pool.ReserveAddresses(expectedClientID, [][]byte{expectedIAID})
|
||||||
expectedIdx := pool.calculateIaIdHash(expectedClientId, expectedIaId)
|
expectedIdx := pool.calculateIAIDHash(expectedClientID, expectedIAID)
|
||||||
|
|
||||||
a, exists := pool.identityAssociations[expectedIdx]
|
a, exists := pool.identityAssociations[expectedIdx]
|
||||||
if !exists {
|
if !exists {
|
||||||
t.Fatalf("Expected to find identity association at %d but didn't", expectedIdx)
|
t.Fatalf("Expected to find identity association at %d but didn't", expectedIdx)
|
||||||
}
|
}
|
||||||
if string(a.ClientId) != string(expectedClientId) || string(a.InterfaceId) != string(expectedIaId) {
|
if string(a.ClientID) != string(expectedClientID) || string(a.InterfaceID) != string(expectedIAID) {
|
||||||
t.Fatalf("Expected ia association with client id %x and ia id %x, but got %x %x respectively",
|
t.Fatalf("Expected ia association with Client id %x and ia id %x, but got %x %x respectively",
|
||||||
expectedClientId, expectedIaId, a.ClientId, a.InterfaceId)
|
expectedClientID, expectedIAID, a.ClientID, a.InterfaceID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReserveAddressKeepsTrackOfUsedAddresses(t *testing.T) {
|
func TestReserveAddressKeepsTrackOfUsedAddresses(t *testing.T) {
|
||||||
expectedClientId := []byte("client-id")
|
expectedClientID := []byte("Client-id")
|
||||||
expectedIaId := []byte("interface-id")
|
expectedIAID := []byte("interface-id")
|
||||||
expectedTime := time.Now()
|
expectedTime := time.Now()
|
||||||
expectedMaxLifetime := uint32(100)
|
expectedMaxLifetime := uint32(100)
|
||||||
|
|
||||||
pool := NewRandomAddressPool(net.ParseIP("2001:db8:f00f:cafe::1"), 1, expectedMaxLifetime)
|
pool := NewRandomAddressPool(net.ParseIP("2001:db8:f00f:cafe::1"), 1, expectedMaxLifetime)
|
||||||
pool.timeNow = func() time.Time { return expectedTime }
|
pool.timeNow = func() time.Time { return expectedTime }
|
||||||
pool.ReserveAddresses(expectedClientId, [][]byte{expectedIaId})
|
pool.ReserveAddresses(expectedClientID, [][]byte{expectedIAID})
|
||||||
|
|
||||||
_, exists := pool.usedIps[0x01]; if !exists {
|
_, exists := pool.usedIps[0x01]; if !exists {
|
||||||
t.Fatal("'2001:db8:f00f:cafe::1' should be marked as in use")
|
t.Fatal("'2001:db8:f00f:cafe::1' should be marked as in use")
|
||||||
@ -86,14 +86,14 @@ func TestReserveAddressKeepsTrackOfUsedAddresses(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestReserveAddressKeepsTrackOfAssociationExpiration(t *testing.T) {
|
func TestReserveAddressKeepsTrackOfAssociationExpiration(t *testing.T) {
|
||||||
expectedClientId := []byte("client-id")
|
expectedClientID := []byte("Client-id")
|
||||||
expectedIaId := []byte("interface-id")
|
expectedIAID := []byte("interface-id")
|
||||||
expectedTime := time.Now()
|
expectedTime := time.Now()
|
||||||
expectedMaxLifetime := uint32(100)
|
expectedMaxLifetime := uint32(100)
|
||||||
|
|
||||||
pool := NewRandomAddressPool(net.ParseIP("2001:db8:f00f:cafe::1"), 1, expectedMaxLifetime)
|
pool := NewRandomAddressPool(net.ParseIP("2001:db8:f00f:cafe::1"), 1, expectedMaxLifetime)
|
||||||
pool.timeNow = func() time.Time { return expectedTime }
|
pool.timeNow = func() time.Time { return expectedTime }
|
||||||
pool.ReserveAddresses(expectedClientId, [][]byte{expectedIaId})
|
pool.ReserveAddresses(expectedClientID, [][]byte{expectedIAID})
|
||||||
|
|
||||||
expiration := pool.identityAssociationExpirations.Peek().(*AssociationExpiration)
|
expiration := pool.identityAssociationExpirations.Peek().(*AssociationExpiration)
|
||||||
if expiration == nil {
|
if expiration == nil {
|
||||||
@ -106,15 +106,15 @@ func TestReserveAddressKeepsTrackOfAssociationExpiration(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestReserveAddressReturnsExistingAssociation(t *testing.T) {
|
func TestReserveAddressReturnsExistingAssociation(t *testing.T) {
|
||||||
expectedClientId := []byte("client-id")
|
expectedClientID := []byte("Client-id")
|
||||||
expectedIaId := []byte("interface-id")
|
expectedIAID := []byte("interface-id")
|
||||||
expectedTime := time.Now()
|
expectedTime := time.Now()
|
||||||
expectedMaxLifetime := uint32(100)
|
expectedMaxLifetime := uint32(100)
|
||||||
|
|
||||||
pool := NewRandomAddressPool(net.ParseIP("2001:db8:f00f:cafe::1"), 1, expectedMaxLifetime)
|
pool := NewRandomAddressPool(net.ParseIP("2001:db8:f00f:cafe::1"), 1, expectedMaxLifetime)
|
||||||
pool.timeNow = func() time.Time { return expectedTime }
|
pool.timeNow = func() time.Time { return expectedTime }
|
||||||
firstAssociation, _ := pool.ReserveAddresses(expectedClientId, [][]byte{expectedIaId})
|
firstAssociation, _ := pool.ReserveAddresses(expectedClientID, [][]byte{expectedIAID})
|
||||||
secondAssociation, _ := pool.ReserveAddresses(expectedClientId, [][]byte{expectedIaId})
|
secondAssociation, _ := pool.ReserveAddresses(expectedClientID, [][]byte{expectedIAID})
|
||||||
|
|
||||||
if len(firstAssociation) < 1 {
|
if len(firstAssociation) < 1 {
|
||||||
t.Fatalf("No associations returned from the first call to ReserveAddresses")
|
t.Fatalf("No associations returned from the first call to ReserveAddresses")
|
||||||
@ -122,24 +122,24 @@ func TestReserveAddressReturnsExistingAssociation(t *testing.T) {
|
|||||||
if len(secondAssociation) < 1 {
|
if len(secondAssociation) < 1 {
|
||||||
t.Fatalf("No associations returned from the second call to ReserveAddresses")
|
t.Fatalf("No associations returned from the second call to ReserveAddresses")
|
||||||
}
|
}
|
||||||
if string(firstAssociation[0].IpAddress) != string(secondAssociation[0].IpAddress) {
|
if string(firstAssociation[0].IPAddress) != string(secondAssociation[0].IPAddress) {
|
||||||
t.Fatal("Expected return of the same ip address on both invocations")
|
t.Fatal("Expected return of the same ip address on both invocations")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReleaseAddress(t *testing.T) {
|
func TestReleaseAddress(t *testing.T) {
|
||||||
expectedClientId := []byte("client-id")
|
expectedClientID := []byte("Client-id")
|
||||||
expectedIaId := []byte("interface-id")
|
expectedIAID := []byte("interface-id")
|
||||||
expectedTime := time.Now()
|
expectedTime := time.Now()
|
||||||
expectedMaxLifetime := uint32(100)
|
expectedMaxLifetime := uint32(100)
|
||||||
|
|
||||||
pool := NewRandomAddressPool(net.ParseIP("2001:db8:f00f:cafe::1"), 1, expectedMaxLifetime)
|
pool := NewRandomAddressPool(net.ParseIP("2001:db8:f00f:cafe::1"), 1, expectedMaxLifetime)
|
||||||
pool.timeNow = func() time.Time { return expectedTime }
|
pool.timeNow = func() time.Time { return expectedTime }
|
||||||
a, _ := pool.ReserveAddresses(expectedClientId, [][]byte{expectedIaId})
|
a, _ := pool.ReserveAddresses(expectedClientID, [][]byte{expectedIAID})
|
||||||
|
|
||||||
pool.ReleaseAddresses(expectedClientId, [][]byte{expectedIaId})
|
pool.ReleaseAddresses(expectedClientID, [][]byte{expectedIAID})
|
||||||
|
|
||||||
_, exists := pool.identityAssociations[pool.calculateIaIdHash(expectedClientId, expectedIaId)]; if exists {
|
_, exists := pool.identityAssociations[pool.calculateIAIDHash(expectedClientID, expectedIAID)]; if exists {
|
||||||
t.Fatalf("identity association for %v should've been removed, but is still available", a[0].IpAddress)
|
t.Fatalf("identity association for %v should've been removed, but is still available", a[0].IPAddress)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,11 +18,11 @@ var bootIPv6Cmd = &cobra.Command{
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf("Error reading flag: %s", err)
|
fatalf("Error reading flag: %s", err)
|
||||||
}
|
}
|
||||||
ipxeUrl, err := cmd.Flags().GetString("ipxe-url")
|
ipxeURL, err := cmd.Flags().GetString("ipxe-url")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf("Error reading flag: %s", err)
|
fatalf("Error reading flag: %s", err)
|
||||||
}
|
}
|
||||||
httpBootUrl, err := cmd.Flags().GetString("httpboot-url")
|
httpBootURL, err := cmd.Flags().GetString("httpboot-url")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf("Error reading flag: %s", err)
|
fatalf("Error reading flag: %s", err)
|
||||||
}
|
}
|
||||||
@ -40,10 +40,10 @@ var bootIPv6Cmd = &cobra.Command{
|
|||||||
fatalf("Please specify address to bind to")
|
fatalf("Please specify address to bind to")
|
||||||
} else {
|
} else {
|
||||||
}
|
}
|
||||||
if ipxeUrl == "" {
|
if ipxeURL == "" {
|
||||||
fatalf("Please specify ipxe config file url")
|
fatalf("Please specify ipxe config file url")
|
||||||
}
|
}
|
||||||
if httpBootUrl == "" {
|
if httpBootURL == "" {
|
||||||
fatalf("Please specify httpboot url")
|
fatalf("Please specify httpboot url")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ var bootIPv6Cmd = &cobra.Command{
|
|||||||
dnsServerAddresses = append(dnsServerAddresses, net.ParseIP(dnsServerAddress))
|
dnsServerAddresses = append(dnsServerAddresses, net.ParseIP(dnsServerAddress))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.BootConfig = dhcp6.MakeStaticBootConfiguration(httpBootUrl, ipxeUrl, preference,
|
s.BootConfig = dhcp6.MakeStaticBootConfiguration(httpBootURL, ipxeURL, preference,
|
||||||
cmd.Flags().Changed("preference"), dnsServerAddresses)
|
cmd.Flags().Changed("preference"), dnsServerAddresses)
|
||||||
|
|
||||||
addressPoolStart, err := cmd.Flags().GetString("address-pool-start")
|
addressPoolStart, err := cmd.Flags().GetString("address-pool-start")
|
||||||
|
@ -20,7 +20,7 @@ var ipv6ApiCmd = &cobra.Command{
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf("Error reading flag: %s", err)
|
fatalf("Error reading flag: %s", err)
|
||||||
}
|
}
|
||||||
apiUrl, err := cmd.Flags().GetString("api-request-url")
|
apiURL, err := cmd.Flags().GetString("api-request-url")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf("Error reading flag: %s", err)
|
fatalf("Error reading flag: %s", err)
|
||||||
}
|
}
|
||||||
@ -41,7 +41,7 @@ var ipv6ApiCmd = &cobra.Command{
|
|||||||
fatalf("Please specify address to bind to")
|
fatalf("Please specify address to bind to")
|
||||||
} else {
|
} else {
|
||||||
}
|
}
|
||||||
if apiUrl == "" {
|
if apiURL == "" {
|
||||||
fatalf("Please specify ipxe config file url")
|
fatalf("Please specify ipxe config file url")
|
||||||
}
|
}
|
||||||
s.Address = addr
|
s.Address = addr
|
||||||
@ -59,7 +59,7 @@ var ipv6ApiCmd = &cobra.Command{
|
|||||||
dnsServerAddresses = append(dnsServerAddresses, net.ParseIP(dnsServerAddress))
|
dnsServerAddresses = append(dnsServerAddresses, net.ParseIP(dnsServerAddress))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.BootConfig = dhcp6.MakeApiBootConfiguration(apiUrl, apiTimeout, preference,
|
s.BootConfig = dhcp6.MakeApiBootConfiguration(apiURL, apiTimeout, preference,
|
||||||
cmd.Flags().Changed("preference"), dnsServerAddresses)
|
cmd.Flags().Changed("preference"), dnsServerAddresses)
|
||||||
|
|
||||||
addressPoolStart, err := cmd.Flags().GetString("address-pool-start")
|
addressPoolStart, err := cmd.Flags().GetString("address-pool-start")
|
||||||
@ -81,7 +81,7 @@ var ipv6ApiCmd = &cobra.Command{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func serverv6ApiConfigFlags(cmd *cobra.Command) {
|
func serverv6APIConfigFlags(cmd *cobra.Command) {
|
||||||
cmd.Flags().StringP("listen-addr", "", "", "IPv6 address to listen on")
|
cmd.Flags().StringP("listen-addr", "", "", "IPv6 address to listen on")
|
||||||
cmd.Flags().StringP("api-request-url", "", "", "Ipv6-specific API server url")
|
cmd.Flags().StringP("api-request-url", "", "", "Ipv6-specific API server url")
|
||||||
cmd.Flags().Duration("api-request-timeout", 5*time.Second, "Timeout for request to the API server")
|
cmd.Flags().Duration("api-request-timeout", 5*time.Second, "Timeout for request to the API server")
|
||||||
@ -95,6 +95,6 @@ func serverv6ApiConfigFlags(cmd *cobra.Command) {
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(ipv6ApiCmd)
|
rootCmd.AddCommand(ipv6ApiCmd)
|
||||||
serverv6ApiConfigFlags(ipv6ApiCmd)
|
serverv6APIConfigFlags(ipv6ApiCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,13 +34,13 @@ func (s *ServerV6) serveDHCP(conn *dhcp6.Conn) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
marshalled_response, err := response.Marshal()
|
marshalledResponse, err := response.Marshal()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log("dhcpv6", fmt.Sprintf("Error marshalling response: %s", response.Type, response.TransactionID, err))
|
s.log("dhcpv6", fmt.Sprintf("Error marshalling response: %s", response.Type, response.TransactionID, err))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := conn.SendDHCP(src, marshalled_response); err != nil {
|
if err := conn.SendDHCP(src, marshalledResponse); err != nil {
|
||||||
s.log("dhcpv6", fmt.Sprintf("Error sending reply (%d) (%d): %s", response.Type, response.TransactionID, err))
|
s.log("dhcpv6", fmt.Sprintf("Error sending reply (%d) (%d): %s", response.Type, response.TransactionID, err))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user