diff --git a/dhcp6/conn.go b/dhcp6/conn.go index 9d5c65a..e841a08 100644 --- a/dhcp6/conn.go +++ b/dhcp6/conn.go @@ -1,18 +1,18 @@ package dhcp6 import ( - "net" - "golang.org/x/net/ipv6" "fmt" + "golang.org/x/net/ipv6" + "net" ) // Conn is dhcpv6-specific socket type Conn struct { - conn *ipv6.PacketConn - group net.IP - ifi *net.Interface + conn *ipv6.PacketConn + group net.IP + ifi *net.Interface listenAddress string - listenPort string + listenPort string } // NewConn creates a new Conn bound to specified address and port @@ -23,7 +23,7 @@ func NewConn(addr, port string) (*Conn, error) { } group := net.ParseIP("ff02::1:2") - c, err := net.ListenPacket("udp6", "[::]:" + port) + c, err := net.ListenPacket("udp6", "[::]:"+port) if err != nil { return nil, err } @@ -33,17 +33,17 @@ func NewConn(addr, port string) (*Conn, error) { return nil, err } - if err := pc.SetControlMessage(ipv6.FlagSrc | ipv6.FlagDst, true); err != nil { + if err := pc.SetControlMessage(ipv6.FlagSrc|ipv6.FlagDst, true); err != nil { pc.Close() return nil, err } return &Conn{ - conn: pc, - group: group, - ifi: ifi, + conn: pc, + group: group, + ifi: ifi, listenAddress: addr, - listenPort: port, + listenPort: port, }, nil } @@ -110,10 +110,11 @@ func (c *Conn) RecvDHCP() (*Packet, net.IP, error) { // SendDHCP sends a dhcp packet to the specified ip address using Conn func (c *Conn) SendDHCP(dst net.IP, p []byte) error { dstAddr := &net.UDPAddr{ - IP: dst, + IP: dst, Port: 546, } - _, err := c.conn.WriteTo(p, nil, dstAddr); if err != nil { + _, err := c.conn.WriteTo(p, nil, dstAddr) + if err != nil { return fmt.Errorf("Error sending a reply to %s: %s", dst.String(), err) } return nil @@ -122,4 +123,4 @@ func (c *Conn) SendDHCP(dst net.IP, p []byte) error { // SourceHardwareAddress returns hardware address of the interface used by Conn func (c *Conn) SourceHardwareAddress() net.HardwareAddr { return c.ifi.HardwareAddr -} \ No newline at end of file +} diff --git a/dhcp6/options.go b/dhcp6/options.go index ce91f98..5c18d19 100644 --- a/dhcp6/options.go +++ b/dhcp6/options.go @@ -1,58 +1,58 @@ package dhcp6 import ( + "bytes" "encoding/binary" "fmt" - "bytes" "net" ) // DHCPv6 option IDs const ( // Client ID Option - OptClientID uint16 = 1 + OptClientID uint16 = 1 // Server ID Option - OptServerID = 2 + OptServerID = 2 // Identity Association for Non-temporary Addresses Option - OptIaNa = 3 + OptIaNa = 3 // Identity Association for Temporary Addresses Option - OptIaTa = 4 + OptIaTa = 4 // IA Address Option - OptIaAddr = 5 + OptIaAddr = 5 // Option Request Option - OptOro = 6 + OptOro = 6 // Preference Option - OptPreference = 7 + OptPreference = 7 // Elapsed Time Option - OptElapsedTime = 8 + OptElapsedTime = 8 // Relay Message Option - OptRelayMessage = 9 + OptRelayMessage = 9 // Authentication Option - OptAuth = 11 + OptAuth = 11 // Server Unicast Option - OptUnicast = 12 + OptUnicast = 12 // Status Code Option - OptStatusCode = 13 + OptStatusCode = 13 // Rapid Commit Option - OptRapidCommit = 14 + OptRapidCommit = 14 // User Class Option - OptUserClass = 15 + OptUserClass = 15 // Vendor Class Option - OptVendorClass = 16 + OptVendorClass = 16 // Vendor-specific Information Option - OptVendorOpts = 17 + OptVendorOpts = 17 // Interface-Id Option - OptInterfaceID = 18 + OptInterfaceID = 18 // Reconfigure Message Option - OptReconfMsg = 19 + OptReconfMsg = 19 // Reconfigure Accept Option - OptReconfAccept = 20 + OptReconfAccept = 20 // Recursive DNS name servers Option - OptRecursiveDNS = 23 + OptRecursiveDNS = 23 // Boot File URL Option - OptBootfileURL = 59 + OptBootfileURL = 59 // Boot File Parameters Option - OptBootfileParam = 60 + OptBootfileParam = 60 // Client Architecture Type Option OptClientArchType = 61 ) @@ -66,7 +66,7 @@ type Option struct { // MakeOption creates an Option with given ID and value 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} } // Options contains all options of a DHCPv6 packet @@ -80,7 +80,7 @@ func UnmarshalOptions(bs []byte) (Options, error) { if err != nil { return nil, err } - ret[o.ID] = append(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 ret, nil @@ -95,7 +95,7 @@ func UnmarshalOption(bs []byte) (*Option, error) { // parse server_id //parse ipaddr case OptOro: - if optionLength% 2 != 0 { + if optionLength%2 != 0 { return nil, fmt.Errorf("OptionID request for options (6) length should be even number of bytes: %d", optionLength) } default: @@ -104,14 +104,14 @@ 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 } // HumanReadable presents DHCPv6 options in a human-readable form func (o Options) HumanReadable() []string { ret := make([]string, 0, len(o)) - for _, multipleOptions := range(o) { - for _, option := range(multipleOptions) { + for _, multipleOptions := range o { + for _, option := range multipleOptions { switch option.ID { case 3: ret = append(ret, o.humanReadableIaNa(*option)...) @@ -137,7 +137,6 @@ func (o Options) humanReadableIaNa(opt Option) []string { l := uint16(binary.BigEndian.Uint16(iaOptions[2:4])) id := uint16(binary.BigEndian.Uint16(iaOptions[0:2])) - switch id { case OptIaAddr: ip := make(net.IP, 16) @@ -157,7 +156,8 @@ func (o Options) humanReadableIaNa(opt Option) []string { // Add adds an option to Options func (o Options) Add(option *Option) { - _, present := o[option.ID]; if !present { + _, present := o[option.ID] + if !present { o[option.ID] = make([]*Option, 0) } o[option.ID] = append(o[option.ID], option) @@ -168,7 +168,7 @@ func (o Options) Add(option *Option) { // (an IA Address Option or a Status Option) func MakeIaNaOption(iaid []byte, t1, t2 uint32, iaOption *Option) *Option { serializedIaOption, _ := iaOption.Marshal() - value := make([]byte, 12 + len(serializedIaOption)) + value := make([]byte, 12+len(serializedIaOption)) copy(value[0:], iaid[0:4]) binary.BigEndian.PutUint32(value[4:], t1) binary.BigEndian.PutUint32(value[8:], t2) @@ -188,7 +188,7 @@ func MakeIaAddrOption(addr net.IP, preferredLifetime, validLifetime uint32) *Opt // MakeStatusOption creates a Status Option with given status code and message func MakeStatusOption(statusCode uint16, message string) *Option { - value := make([]byte, 2 + len(message)) + value := make([]byte, 2+len(message)) binary.BigEndian.PutUint16(value[0:], statusCode) copy(value[2:], []byte(message)) return MakeOption(OptStatusCode, value) @@ -206,8 +206,8 @@ func MakeDNSServersOption(addresses []net.IP) *Option { // Marshal serializes Options func (o Options) Marshal() ([]byte, error) { buffer := bytes.NewBuffer(make([]byte, 0, 1446)) - for _, multipleOptions := range(o) { - for _, o := range (multipleOptions) { + for _, multipleOptions := range o { + for _, o := range multipleOptions { serialized, err := o.Marshal() if err != nil { return nil, fmt.Errorf("Error serializing option value: %s", err) @@ -222,7 +222,7 @@ func (o Options) Marshal() ([]byte, error) { // Marshal serializes the Option func (o *Option) Marshal() ([]byte, error) { - buffer := bytes.NewBuffer(make([]byte, 0, o.Length + 2)) + buffer := bytes.NewBuffer(make([]byte, 0, o.Length+2)) err := binary.Write(buffer, binary.BigEndian, o.ID) if err != nil { @@ -243,7 +243,8 @@ func (o *Option) Marshal() ([]byte, error) { func (o Options) UnmarshalOptionRequestOption() map[uint16]bool { ret := make(map[uint16]bool) - _, present := o[OptOro]; if !present { + _, present := o[OptOro] + if !present { return ret } @@ -315,8 +316,8 @@ func (o Options) IaNaIDs() [][]byte { options, exists := o[OptIaNa] ret := make([][]byte, 0) if exists { - for _, option := range(options) { - ret = append(ret, option.Value[0:4]) + for _, option := range options { + ret = append(ret, option.Value[0:4]) } return ret } @@ -340,4 +341,3 @@ func (o Options) BootFileURL() []byte { } return nil } - diff --git a/dhcp6/options_test.go b/dhcp6/options_test.go index 877c017..e5d0c09 100644 --- a/dhcp6/options_test.go +++ b/dhcp6/options_test.go @@ -1,9 +1,9 @@ package dhcp6 import ( - "testing" "encoding/binary" "net" + "testing" ) func TestMarshalOption(t *testing.T) { @@ -85,8 +85,8 @@ func TestMakeStatusOption(t *testing.T) { 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) + if noAddrOption.Length != uint16(2+len(expectedMessage)) { + t.Fatalf("Expected option length of %d, got %d", 2+len(expectedMessage), noAddrOption.Length) } if binary.BigEndian.Uint16(noAddrOption.Value[0:2]) != expectedStatusCode { t.Fatalf("Expected status code 2, got %d", binary.BigEndian.Uint16(noAddrOption.Value[0:2])) diff --git a/dhcp6/packet.go b/dhcp6/packet.go index b4f5a53..2eb19f7 100644 --- a/dhcp6/packet.go +++ b/dhcp6/packet.go @@ -1,8 +1,8 @@ package dhcp6 import ( - "fmt" "bytes" + "fmt" ) // MessageType contains ID identifying DHCP message type. See RFC 3315 @@ -50,7 +50,7 @@ func (p *Packet) Marshal() ([]byte, error) { return nil, fmt.Errorf("packet has malformed options section: %s", err) } - ret := make([]byte, len(marshalledOptions) + 4, len(marshalledOptions) + 4) + ret := make([]byte, len(marshalledOptions)+4, len(marshalledOptions)+4) ret[0] = byte(p.Type) copy(ret[1:], p.TransactionID[:]) copy(ret[4:], marshalledOptions) diff --git a/dhcp6/packet_builder.go b/dhcp6/packet_builder.go index d93d31f..9281ecf 100644 --- a/dhcp6/packet_builder.go +++ b/dhcp6/packet_builder.go @@ -1,8 +1,8 @@ package dhcp6 import ( - "hash/fnv" "encoding/binary" + "hash/fnv" "net" ) @@ -38,8 +38,8 @@ func (b *PacketBuilder) BuildResponse(in *Packet, serverDUID []byte, configurati } 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 + 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()) if err != nil { @@ -59,18 +59,21 @@ func (b *PacketBuilder) makeMsgAdvertise(transactionID [3]byte, serverDUID, clie associations []*IdentityAssociation, bootFileURL, preference []byte, dnsServers []net.IP) *Packet { retOptions := make(Options) retOptions.Add(MakeOption(OptClientID, clientID)) - for _, association := range(associations) { + for _, association := range associations { retOptions.Add(MakeIaNaOption(association.InterfaceID, b.calculateT1(), b.calculateT2(), MakeIaAddrOption(association.IPAddress, b.PreferredLifetime, b.ValidLifetime))) } retOptions.Add(MakeOption(OptServerID, serverDUID)) - if 0x10 == clientArchType { // HTTPClient - retOptions.Add(MakeOption(OptVendorClass, []byte {0, 0, 0, 0, 0, 10, 72, 84, 84, 80, 67, 108, 105, 101, 110, 116})) // HTTPClient + if 0x10 == clientArchType { // HTTPClient + retOptions.Add(MakeOption(OptVendorClass, []byte{0, 0, 0, 0, 0, 10, 72, 84, 84, 80, 67, 108, 105, 101, 110, 116})) // HTTPClient } retOptions.Add(MakeOption(OptBootfileURL, bootFileURL)) if preference != nil { - retOptions.Add(MakeOption(OptPreference, preference))} - if len(dnsServers) > 0 { retOptions.Add(MakeDNSServersOption(dnsServers)) } + retOptions.Add(MakeOption(OptPreference, preference)) + } + if len(dnsServers) > 0 { + retOptions.Add(MakeDNSServersOption(dnsServers)) + } return &Packet{Type: MsgAdvertise, TransactionID: transactionID, Options: retOptions} } @@ -79,20 +82,22 @@ func (b *PacketBuilder) makeMsgReply(transactionID [3]byte, serverDUID, clientID associations []*IdentityAssociation, iasWithoutAddresses [][]byte, bootFileURL []byte, dnsServers []net.IP, err error) *Packet { retOptions := make(Options) retOptions.Add(MakeOption(OptClientID, clientID)) - for _, association := range(associations) { + for _, association := range associations { retOptions.Add(MakeIaNaOption(association.InterfaceID, b.calculateT1(), b.calculateT2(), MakeIaAddrOption(association.IPAddress, b.PreferredLifetime, b.ValidLifetime))) } - for _, ia := range(iasWithoutAddresses) { + for _, ia := range iasWithoutAddresses { retOptions.Add(MakeIaNaOption(ia, b.calculateT1(), b.calculateT2(), MakeStatusOption(2, err.Error()))) } retOptions.Add(MakeOption(OptServerID, serverDUID)) - if 0x10 == clientArchType { // HTTPClient - retOptions.Add(MakeOption(OptVendorClass, []byte {0, 0, 0, 0, 0, 10, 72, 84, 84, 80, 67, 108, 105, 101, 110, 116})) // HTTPClient + if 0x10 == clientArchType { // HTTPClient + retOptions.Add(MakeOption(OptVendorClass, []byte{0, 0, 0, 0, 0, 10, 72, 84, 84, 80, 67, 108, 105, 101, 110, 116})) // HTTPClient } retOptions.Add(MakeOption(OptBootfileURL, bootFileURL)) - if len(dnsServers) > 0 { retOptions.Add(MakeDNSServersOption(dnsServers)) } + if len(dnsServers) > 0 { + retOptions.Add(MakeDNSServersOption(dnsServers)) + } return &Packet{Type: MsgReply, TransactionID: transactionID, Options: retOptions} } @@ -102,11 +107,13 @@ func (b *PacketBuilder) makeMsgInformationRequestReply(transactionID [3]byte, se retOptions := make(Options) retOptions.Add(MakeOption(OptClientID, clientID)) retOptions.Add(MakeOption(OptServerID, serverDUID)) - if 0x10 == clientArchType { // HTTPClient - retOptions.Add(MakeOption(OptVendorClass, []byte {0, 0, 0, 0, 0, 10, 72, 84, 84, 80, 67, 108, 105, 101, 110, 116})) // HTTPClient + if 0x10 == clientArchType { // HTTPClient + retOptions.Add(MakeOption(OptVendorClass, []byte{0, 0, 0, 0, 0, 10, 72, 84, 84, 80, 67, 108, 105, 101, 110, 116})) // HTTPClient } retOptions.Add(MakeOption(OptBootfileURL, bootFileURL)) - if len(dnsServers) > 0 { retOptions.Add(MakeDNSServersOption(dnsServers)) } + if len(dnsServers) > 0 { + retOptions.Add(MakeDNSServersOption(dnsServers)) + } return &Packet{Type: MsgReply, TransactionID: transactionID, Options: retOptions} } @@ -136,7 +143,7 @@ func (b *PacketBuilder) calculateT1() uint32 { } func (b *PacketBuilder) calculateT2() uint32 { - return (b.PreferredLifetime * 4)/5 + return (b.PreferredLifetime * 4) / 5 } func (b *PacketBuilder) extractLLAddressOrID(optClientID []byte) []byte { @@ -155,12 +162,13 @@ func iasWithoutAddesses(availableAssociations []*IdentityAssociation, allIAs [][ ret := make([][]byte, 0) iasWithAddresses := make(map[uint64]bool) - for _, association := range(availableAssociations) { + for _, association := range availableAssociations { 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) } } diff --git a/dhcp6/packet_builder_test.go b/dhcp6/packet_builder_test.go index 4a149c8..d30a3cc 100644 --- a/dhcp6/packet_builder_test.go +++ b/dhcp6/packet_builder_test.go @@ -1,10 +1,10 @@ package dhcp6 import ( - "testing" "encoding/binary" - "net" "fmt" + "net" + "testing" ) func TestMakeMsgAdvertise(t *testing.T) { @@ -86,7 +86,8 @@ func TestMakeMsgAdvertiseShouldSkipDnsServersIfNoneConfigured(t *testing.T) { 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") } } @@ -168,7 +169,8 @@ func TestMakeNoAddrsAvailable(t *testing.T) { t.Fatalf("Expected server id %v, got %v", expectedClientID, serverIDOption) } - _, exists := msg.Options[OptStatusCode]; if !exists { + _, exists := msg.Options[OptStatusCode] + if !exists { t.Fatalf("Expected status code option to be present") } statusCodeOption := msg.Options[OptStatusCode][0].Value @@ -258,7 +260,8 @@ func TestMakeMsgReplyShouldSkipDnsServersIfNoneWereConfigured(t *testing.T) { 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") } } @@ -413,7 +416,8 @@ func TestMakeMsgInformationRequestReplyShouldSkipDnsServersIfNoneWereConfigured( 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") } } diff --git a/dhcp6/packet_test.go b/dhcp6/packet_test.go index 1f7342f..1acd59e 100644 --- a/dhcp6/packet_test.go +++ b/dhcp6/packet_test.go @@ -1,8 +1,8 @@ package dhcp6 import ( - "testing" "encoding/binary" + "testing" ) func TestShouldDiscardSolicitWithoutBootfileUrlOption(t *testing.T) { @@ -93,10 +93,9 @@ func TestShouldDiscardRequestWithWrongServerId(t *testing.T) { func MakeOptionRequestOptions(options []uint16) *Option { value := make([]byte, len(options)*2) - for i, option := range(options) { + for i, option := range options { 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} } - diff --git a/dhcp6/pool/random_address_pool.go b/dhcp6/pool/random_address_pool.go index 698a445..4ddccd6 100644 --- a/dhcp6/pool/random_address_pool.go +++ b/dhcp6/pool/random_address_pool.go @@ -1,22 +1,22 @@ package pool import ( - "net" - "math/rand" - "time" - "math/big" - "hash/fnv" - "sync" "fmt" "go.universe.tf/netboot/dhcp6" + "hash/fnv" + "math/big" + "math/rand" + "net" + "sync" + "time" ) type associationExpiration struct { expiresAt time.Time - ia *dhcp6.IdentityAssociation + ia *dhcp6.IdentityAssociation } -type fifo struct {q []interface{}} +type fifo struct{ q []interface{} } func newFifo() fifo { return fifo{q: make([]interface{}, 0, 1000)} @@ -80,9 +80,9 @@ func (p *RandomAddressPool) ReserveAddresses(clientID []byte, interfaceIDs [][]b ret := make([]*dhcp6.IdentityAssociation, 0, len(interfaceIDs)) rng := rand.New(rand.NewSource(p.timeNow().UnixNano())) - for _, interfaceID := range (interfaceIDs) { + for _, interfaceID := range interfaceIDs { clientIDHash := p.calculateIAIDHash(clientID, interfaceID) - association, exists := p.identityAssociations[clientIDHash]; + association, exists := p.identityAssociations[clientIDHash] if exists { ret = append(ret, association) @@ -96,13 +96,13 @@ func (p *RandomAddressPool) ReserveAddresses(clientID []byte, interfaceIDs [][]b // we assume that ip addresses adhere to high 64 bits for net and subnet ids, low 64 bits are for host id rule hostOffset := rng.Uint64() % p.poolSize newIP := big.NewInt(0).Add(p.poolStartAddress, big.NewInt(0).SetUint64(hostOffset)) - _, exists := p.usedIps[newIP.Uint64()]; + _, exists := p.usedIps[newIP.Uint64()] if !exists { timeNow := p.timeNow() association := &dhcp6.IdentityAssociation{ClientID: clientID, InterfaceID: interfaceID, - IPAddress: newIP.Bytes(), - CreatedAt: timeNow} + IPAddress: newIP.Bytes(), + CreatedAt: timeNow} p.identityAssociations[clientIDHash] = association p.usedIps[newIP.Uint64()] = struct{}{} p.identityAssociationExpirations.Push(&associationExpiration{expiresAt: p.calculateAssociationExpiration(timeNow), ia: association}) @@ -116,11 +116,11 @@ func (p *RandomAddressPool) ReserveAddresses(clientID []byte, interfaceIDs [][]b } // ReleaseAddresses returns IP addresses associated with ClientID and interfaceIDs back into the address pool -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) { + for _, interfaceID := range interfaceIDs { association, exists := p.identityAssociations[p.calculateIAIDHash(clientID, interfaceID)] if !exists { continue @@ -134,9 +134,13 @@ func (p *RandomAddressPool) ReleaseAddresses(clientID []byte, interfaceIDs [][] // back into the address pool. Note it should be called from under the RandomAddressPool.lock. func (p *RandomAddressPool) expireIdentityAssociations() { for { - if p.identityAssociationExpirations.Size() < 1 { break } + if p.identityAssociationExpirations.Size() < 1 { + break + } expiration := p.identityAssociationExpirations.Peek().(*associationExpiration) - if p.timeNow().Before(expiration.expiresAt) { break } + 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()) @@ -144,7 +148,7 @@ func (p *RandomAddressPool) expireIdentityAssociations() { } func (p *RandomAddressPool) calculateAssociationExpiration(now time.Time) time.Time { - return now.Add(time.Duration(p.validLifetime)*time.Second) + return now.Add(time.Duration(p.validLifetime) * time.Second) } func (p *RandomAddressPool) calculateIAIDHash(clientID, interfaceID []byte) uint64 { diff --git a/dhcp6/pool/random_address_pool_test.go b/dhcp6/pool/random_address_pool_test.go index 192af33..1560881 100644 --- a/dhcp6/pool/random_address_pool_test.go +++ b/dhcp6/pool/random_address_pool_test.go @@ -1,8 +1,8 @@ package pool import ( - "testing" "net" + "testing" "time" ) @@ -22,26 +22,26 @@ func TestReserveAddress(t *testing.T) { 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) { + 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) { + 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) { + 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) { + 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) { + 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) { + 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 { @@ -80,7 +80,8 @@ func TestReserveAddressKeepsTrackOfUsedAddresses(t *testing.T) { pool.timeNow = func() time.Time { return expectedTime } pool.ReserveAddresses(expectedClientID, [][]byte{expectedIAID}) - _, exists := pool.usedIps[0x01]; if !exists { + _, exists := pool.usedIps[0x01] + if !exists { t.Fatal("'2001:db8:f00f:cafe::1' should be marked as in use") } } @@ -139,7 +140,8 @@ func TestReleaseAddress(t *testing.T) { pool.ReleaseAddresses(expectedClientID, [][]byte{expectedIAID}) - _, exists := pool.identityAssociations[pool.calculateIAIDHash(expectedClientID, expectedIAID)]; if exists { + _, exists := pool.identityAssociations[pool.calculateIAIDHash(expectedClientID, expectedIAID)] + if exists { t.Fatalf("identity association for %v should've been removed, but is still available", a[0].IPAddress) } } diff --git a/pixiecore/boot_configuration.go b/pixiecore/boot_configuration.go index f692be0..0420b5e 100644 --- a/pixiecore/boot_configuration.go +++ b/pixiecore/boot_configuration.go @@ -1,13 +1,13 @@ package pixiecore import ( - "net/http" - "time" - "strings" - "fmt" - "net/url" "bytes" + "fmt" "net" + "net/http" + "net/url" + "strings" + "time" ) const X86_HTTP_CLIENT = 0x10 @@ -23,7 +23,7 @@ type StaticBootConfiguration struct { // MakeStaticBootConfiguration creates a new StaticBootConfiguration with provided values func MakeStaticBootConfiguration(httpBootURL, ipxeBootURL string, preference uint8, usePreference bool, - dnsServerAddresses []net.IP) *StaticBootConfiguration { + dnsServerAddresses []net.IP) *StaticBootConfiguration { ret := &StaticBootConfiguration{HTTPBootURL: []byte(httpBootURL), IPxeBootURL: []byte(ipxeBootURL), UsePreference: usePreference} if usePreference { ret.Preference = make([]byte, 1) @@ -63,7 +63,7 @@ type APIBootConfiguration struct { // MakeAPIBootConfiguration creates a new APIBootConfiguration initialized with provided values func MakeAPIBootConfiguration(url string, timeout time.Duration, preference uint8, usePreference bool, - dnsServerAddresses []net.IP) *APIBootConfiguration { + dnsServerAddresses []net.IP) *APIBootConfiguration { if !strings.HasSuffix(url, "/") { url += "/" } diff --git a/pixiecore/cli/bootipv6cmd.go b/pixiecore/cli/bootipv6cmd.go index d1b6843..4d51a32 100644 --- a/pixiecore/cli/bootipv6cmd.go +++ b/pixiecore/cli/bootipv6cmd.go @@ -1,13 +1,13 @@ package cli import ( - "github.com/spf13/cobra" "fmt" + "github.com/spf13/cobra" "go.universe.tf/netboot/dhcp6" "go.universe.tf/netboot/dhcp6/pool" + "go.universe.tf/netboot/pixiecore" "net" "strings" - "go.universe.tf/netboot/pixiecore" ) // pixiecore bootipv6 --listen-addr=2001:db8:f00f:cafe::4/64 --httpboot-url=http://[2001:db8:f00f:cafe::4]/bootx64.efi --ipxe-url=http://[2001:db8:f00f:cafe::4]/script.ipxe @@ -35,7 +35,9 @@ var bootIPv6Cmd = &cobra.Command{ if err != nil { s.Debug = logWithStdFmt } - if debug { s.Debug = logWithStdFmt } + if debug { + s.Debug = logWithStdFmt + } if addr == "" { fatalf("Please specify address to bind to") @@ -79,7 +81,7 @@ var bootIPv6Cmd = &cobra.Command{ fatalf("Error reading flag: %s", err) } s.AddressPool = pool.NewRandomAddressPool(net.ParseIP(addressPoolStart), addressPoolSize, addressPoolValidLifetime) - s.PacketBuilder = dhcp6.MakePacketBuilder(addressPoolValidLifetime - addressPoolValidLifetime*3/100, addressPoolValidLifetime) + s.PacketBuilder = dhcp6.MakePacketBuilder(addressPoolValidLifetime-addressPoolValidLifetime*3/100, addressPoolValidLifetime) fmt.Println(s.Serve()) }, diff --git a/pixiecore/cli/ipv6apicmd.go b/pixiecore/cli/ipv6apicmd.go index 3ed0479..4ecfef9 100644 --- a/pixiecore/cli/ipv6apicmd.go +++ b/pixiecore/cli/ipv6apicmd.go @@ -1,14 +1,14 @@ package cli import ( - "github.com/spf13/cobra" "fmt" + "github.com/spf13/cobra" "go.universe.tf/netboot/dhcp6" "go.universe.tf/netboot/dhcp6/pool" - "time" + "go.universe.tf/netboot/pixiecore" "net" "strings" - "go.universe.tf/netboot/pixiecore" + "time" ) // pixiecore ipv6api --listen-addr=2001:db8:f00f:cafe::4 --api-request-url=http://[2001:db8:f00f:cafe::4]:8888 @@ -36,7 +36,9 @@ var ipv6ApiCmd = &cobra.Command{ if err != nil { s.Debug = logWithStdFmt } - if debug { s.Debug = logWithStdFmt } + if debug { + s.Debug = logWithStdFmt + } if addr == "" { fatalf("Please specify address to bind to") @@ -76,7 +78,7 @@ var ipv6ApiCmd = &cobra.Command{ fatalf("Error reading flag: %s", err) } s.AddressPool = pool.NewRandomAddressPool(net.ParseIP(addressPoolStart), addressPoolSize, addressPoolValidLifetime) - s.PacketBuilder = dhcp6.MakePacketBuilder(addressPoolValidLifetime - addressPoolValidLifetime*3/100, addressPoolValidLifetime) + s.PacketBuilder = dhcp6.MakePacketBuilder(addressPoolValidLifetime-addressPoolValidLifetime*3/100, addressPoolValidLifetime) fmt.Println(s.Serve()) }, @@ -98,4 +100,3 @@ func init() { rootCmd.AddCommand(ipv6ApiCmd) serverv6APIConfigFlags(ipv6ApiCmd) } - diff --git a/pixiecore/dhcpv6.go b/pixiecore/dhcpv6.go index 695c702..d11c981 100644 --- a/pixiecore/dhcpv6.go +++ b/pixiecore/dhcpv6.go @@ -1,8 +1,8 @@ package pixiecore import ( - "go.universe.tf/netboot/dhcp6" "fmt" + "go.universe.tf/netboot/dhcp6" ) func (s *ServerV6) serveDHCP(conn *dhcp6.Conn) error { diff --git a/pixiecore/pixicorev6.go b/pixiecore/pixicorev6.go index e266d03..fc377e2 100644 --- a/pixiecore/pixicorev6.go +++ b/pixiecore/pixicorev6.go @@ -1,25 +1,25 @@ package pixiecore import ( - "go.universe.tf/netboot/dhcp6" - "fmt" - "time" "encoding/binary" + "fmt" + "go.universe.tf/netboot/dhcp6" "net" + "time" ) type ServerV6 struct { - Address string - Port string - Duid []byte + Address string + Port string + Duid []byte - BootConfig dhcp6.BootConfiguration - PacketBuilder *dhcp6.PacketBuilder - AddressPool dhcp6.AddressPool + BootConfig dhcp6.BootConfiguration + PacketBuilder *dhcp6.PacketBuilder + AddressPool dhcp6.AddressPool errs chan error - Log func(subsystem, msg string) + Log func(subsystem, msg string) Debug func(subsystem, msg string) } @@ -82,7 +82,7 @@ func (s *ServerV6) debug(subsystem, format string, args ...interface{}) { } func (s *ServerV6) SetDUID(addr net.HardwareAddr) { - duid := make([]byte, len(addr) + 8) // see rfc3315, section 9.2, DUID-LT + duid := make([]byte, len(addr)+8) // see rfc3315, section 9.2, DUID-LT copy(duid[0:], []byte{0, 1}) //fixed, x0001 copy(duid[2:], []byte{0, 1}) //hw type ethernet, x0001 @@ -94,4 +94,4 @@ func (s *ServerV6) SetDUID(addr net.HardwareAddr) { copy(duid[8:], addr) s.Duid = duid -} \ No newline at end of file +}