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