mirror of
https://github.com/danderson/netboot.git
synced 2026-05-04 20:06:30 +02:00
Bootfile urls can be retrieved via remote api calls now
This commit is contained in:
parent
02db3ab76d
commit
da6402caf7
@ -6,26 +6,13 @@ import (
|
||||
)
|
||||
|
||||
type IdentityAssociation struct {
|
||||
ipAddress net.IP
|
||||
clientId []byte
|
||||
interfaceId []byte
|
||||
createdAt time.Time
|
||||
IpAddress net.IP
|
||||
ClientId []byte
|
||||
InterfaceId []byte
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
type AddressPool interface {
|
||||
ReserveAddress(clientId, interfaceId []byte) *IdentityAssociation
|
||||
ReleaseAddress(clientId, interfaceId []byte)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
79
dhcp6/boot_configuration.go
Normal file
79
dhcp6/boot_configuration.go
Normal file
@ -0,0 +1,79 @@
|
||||
package dhcp6
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
"strings"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"bytes"
|
||||
)
|
||||
|
||||
type BootConfiguration interface {
|
||||
GetBootUrl(id []byte, clientArchType uint16) (string, error)
|
||||
}
|
||||
|
||||
type StaticBootConfiguration struct {
|
||||
HttpBootUrl string
|
||||
IPxeBootUrl string
|
||||
}
|
||||
|
||||
func MakeStaticBootConfiguration(httpBootUrl, ipxeBootUrl string) *StaticBootConfiguration {
|
||||
return &StaticBootConfiguration{HttpBootUrl: httpBootUrl, IPxeBootUrl: ipxeBootUrl}
|
||||
}
|
||||
|
||||
func (bc *StaticBootConfiguration) GetBootUrl(id []byte, clientArchType uint16) (string, error) {
|
||||
if 0x10 == clientArchType {
|
||||
return bc.HttpBootUrl, nil
|
||||
}
|
||||
return bc.IPxeBootUrl, nil
|
||||
}
|
||||
|
||||
type ApiBootConfiguration struct {
|
||||
client *http.Client
|
||||
urlPrefix string
|
||||
}
|
||||
|
||||
func MakeApiBootConfiguration(url string, timeout time.Duration) *ApiBootConfiguration {
|
||||
if !strings.HasSuffix(url, "/") {
|
||||
url += "/"
|
||||
}
|
||||
return &ApiBootConfiguration{
|
||||
client: &http.Client{Timeout: timeout},
|
||||
urlPrefix: url + "v1",
|
||||
}
|
||||
}
|
||||
|
||||
func (bc *ApiBootConfiguration) GetBootUrl(id []byte, clientArchType uint16) (string, error) {
|
||||
reqURL := fmt.Sprintf("%s/boot/%x/%d", bc.urlPrefix, id, clientArchType)
|
||||
resp, err := bc.client.Get(reqURL)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
resp.Body.Close()
|
||||
return "", fmt.Errorf("%s: %s", reqURL, http.StatusText(resp.StatusCode))
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
buf.ReadFrom(resp.Body)
|
||||
url, _ := bc.makeURLAbsolute(buf.String())
|
||||
|
||||
return url, nil
|
||||
}
|
||||
|
||||
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)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
u = base.ResolveReference(u)
|
||||
}
|
||||
return u.String(), nil
|
||||
}
|
||||
@ -3,6 +3,7 @@ package dhcp6
|
||||
import (
|
||||
"fmt"
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
)
|
||||
|
||||
type MessageType uint8
|
||||
@ -30,12 +31,11 @@ type Packet struct {
|
||||
}
|
||||
|
||||
type PacketBuilder struct {
|
||||
ServerDuid []byte
|
||||
PreferredLifetime uint32
|
||||
ValidLifetime uint32
|
||||
BootFileUrlForHttpBoot string
|
||||
BootFileUrlForIpxe string
|
||||
Addresses AddressPool
|
||||
ServerDuid []byte
|
||||
PreferredLifetime uint32
|
||||
ValidLifetime uint32
|
||||
BootFileUrl BootConfiguration
|
||||
Addresses AddressPool
|
||||
}
|
||||
|
||||
func MakePacket(bs []byte, packetLength int) (*Packet, error) {
|
||||
@ -48,10 +48,10 @@ func MakePacket(bs []byte, packetLength int) (*Packet, error) {
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func MakePacketBuilder(serverDuid []byte, preferredLifetime, validLifetime uint32, httpBootFileUrl, ipxeBootFileUrl string,
|
||||
func MakePacketBuilder(serverDuid []byte, preferredLifetime, validLifetime uint32, bootFileUrl BootConfiguration,
|
||||
addressPool AddressPool) *PacketBuilder {
|
||||
return &PacketBuilder{ServerDuid: serverDuid, PreferredLifetime: preferredLifetime, ValidLifetime: validLifetime,
|
||||
BootFileUrlForHttpBoot: httpBootFileUrl, BootFileUrlForIpxe: ipxeBootFileUrl, Addresses: addressPool}
|
||||
BootFileUrl: bootFileUrl, Addresses: addressPool}
|
||||
}
|
||||
|
||||
func (p *Packet) Marshal() ([]byte, error) {
|
||||
@ -133,11 +133,11 @@ func (b *PacketBuilder) BuildResponse(in *Packet) *Packet {
|
||||
case MsgSolicit:
|
||||
association := b.Addresses.ReserveAddress(in.Options.ClientId(), in.Options.IaNaId())
|
||||
return b.MakeMsgAdvertise(in.TransactionID, in.Options.ClientId(), in.Options.IaNaId(),
|
||||
in.Options.ClientArchType(), association.ipAddress)
|
||||
in.Options.ClientArchType(), association.IpAddress)
|
||||
case MsgRequest:
|
||||
association := b.Addresses.ReserveAddress(in.Options.ClientId(), in.Options.IaNaId())
|
||||
return b.MakeMsgReply(in.TransactionID, in.Options.ClientId(), in.Options.IaNaId(),
|
||||
in.Options.ClientArchType(), association.ipAddress)
|
||||
in.Options.ClientArchType(), association.IpAddress)
|
||||
case MsgInformationRequest:
|
||||
return b.MakeMsgInformationRequestReply(in.TransactionID, in.Options.ClientId(),
|
||||
in.Options.ClientArchType())
|
||||
@ -155,13 +155,16 @@ func (b *PacketBuilder) MakeMsgAdvertise(transactionId [3]byte, clientId, iaId [
|
||||
ret_options.AddOption(MakeIaNaOption(iaId, b.calculateT1(), b.calculateT2(),
|
||||
MakeIaAddrOption(ipAddress, b.PreferredLifetime, b.ValidLifetime)))
|
||||
ret_options.AddOption(MakeOption(OptServerId, b.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
|
||||
ret_options.AddOption(MakeOption(OptBootfileUrl, []byte(b.BootFileUrlForHttpBoot)))
|
||||
} else {
|
||||
ret_options.AddOption(MakeOption(OptBootfileUrl, []byte(b.BootFileUrlForIpxe)))
|
||||
}
|
||||
bootfileUrl, err := b.BootFileUrl.GetBootUrl(b.ExtractLLAddressOrId(clientId), clientArchType)
|
||||
if err != nil {
|
||||
fmt.Printf("!!!!!!!!!!!!!!!!!!!!!!!! %s", err)
|
||||
return nil
|
||||
}
|
||||
ret_options.AddOption(MakeOption(OptBootfileUrl, []byte(bootfileUrl)))
|
||||
|
||||
// ret_options.AddOption(OptRecursiveDns, net.ParseIP("2001:db8:f00f:cafe::1"))
|
||||
//ret_options.AddOption(OptBootfileParam, []byte("http://")
|
||||
//ret.Options[OptPreference] = [][]byte("http://")
|
||||
@ -175,13 +178,14 @@ func (b *PacketBuilder) MakeMsgReply(transactionId [3]byte, clientId, iaId []byt
|
||||
ret_options.AddOption(MakeIaNaOption(iaId, b.calculateT1(), b.calculateT2(),
|
||||
MakeIaAddrOption(ipAddress, b.PreferredLifetime, b.ValidLifetime)))
|
||||
ret_options.AddOption(MakeOption(OptServerId, b.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
|
||||
ret_options.AddOption(MakeOption(OptBootfileUrl, []byte(b.BootFileUrlForHttpBoot)))
|
||||
} else {
|
||||
ret_options.AddOption(MakeOption(OptBootfileUrl, []byte(b.BootFileUrlForIpxe)))
|
||||
}
|
||||
bootfileUrl, err := b.BootFileUrl.GetBootUrl(b.ExtractLLAddressOrId(clientId), clientArchType)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
ret_options.AddOption(MakeOption(OptBootfileUrl, []byte(bootfileUrl)))
|
||||
|
||||
return &Packet{Type: MsgReply, TransactionID: transactionId, Options: ret_options}
|
||||
}
|
||||
@ -190,13 +194,14 @@ func (b *PacketBuilder) MakeMsgInformationRequestReply(transactionId [3]byte, cl
|
||||
ret_options := make(Options)
|
||||
ret_options.AddOption(MakeOption(OptClientId, clientId))
|
||||
ret_options.AddOption(MakeOption(OptServerId, b.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
|
||||
ret_options.AddOption(MakeOption(OptBootfileUrl, []byte(b.BootFileUrlForHttpBoot)))
|
||||
} else {
|
||||
ret_options.AddOption(MakeOption(OptBootfileUrl, []byte(b.BootFileUrlForIpxe)))
|
||||
}
|
||||
bootfileUrl, err := b.BootFileUrl.GetBootUrl(b.ExtractLLAddressOrId(clientId), clientArchType)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
ret_options.AddOption(MakeOption(OptBootfileUrl, []byte(bootfileUrl)))
|
||||
|
||||
return &Packet{Type: MsgReply, TransactionID: transactionId, Options: ret_options}
|
||||
}
|
||||
@ -221,3 +226,14 @@ func (b *PacketBuilder) calculateT2() uint32 {
|
||||
return (b.PreferredLifetime * 4)/5
|
||||
}
|
||||
|
||||
func (b *PacketBuilder) ExtractLLAddressOrId(optClientId []byte) []byte {
|
||||
idType := binary.BigEndian.Uint16(optClientId[0:2])
|
||||
switch idType {
|
||||
case 1:
|
||||
return optClientId[8:]
|
||||
case 3:
|
||||
return optClientId[4:]
|
||||
default:
|
||||
return optClientId[2:]
|
||||
}
|
||||
}
|
||||
@ -12,7 +12,8 @@ func TestMakeMsgAdvertise(t *testing.T) {
|
||||
transactionId := [3]byte{'1', '2', '3'}
|
||||
expectedIp := net.ParseIP("2001:db8:f00f:cafe::1")
|
||||
|
||||
builder := MakePacketBuilder(expectedServerId, 90, 100, "httpbootfileurl", "ipxebootfileurl",
|
||||
bootConfig := MakeStaticBootConfiguration("httpbootfileurl", "ipxebootfileurl")
|
||||
builder := MakePacketBuilder(expectedServerId, 90, 100, bootConfig,
|
||||
NewRandomAddressPool(net.ParseIP("2001:db8:f00f:cafe::1"), net.ParseIP("2001:db8:f00f:cafe::1"), 100))
|
||||
|
||||
msg := builder.MakeMsgAdvertise(transactionId, expectedClientId, []byte("1234"), 0x11, expectedIp)
|
||||
@ -63,7 +64,8 @@ func TestMakeMsgAdvertiseWithHttpClientArch(t *testing.T) {
|
||||
transactionId := [3]byte{'1', '2', '3'}
|
||||
expectedIp := net.ParseIP("2001:db8:f00f:cafe::1")
|
||||
|
||||
builder := MakePacketBuilder(expectedServerId, 90, 100, "httpbootfileurl", "ipxebootfileurl",
|
||||
bootConfig := MakeStaticBootConfiguration("httpbootfileurl", "ipxebootfileurl")
|
||||
builder := MakePacketBuilder(expectedServerId, 90, 100, bootConfig,
|
||||
NewRandomAddressPool(net.ParseIP("2001:db8:f00f:cafe::1"), net.ParseIP("2001:db8:f00f:cafe::1"), 100))
|
||||
|
||||
msg := builder.MakeMsgAdvertise(transactionId, expectedClientId, []byte("1234"), 0x10, expectedIp)
|
||||
@ -85,7 +87,8 @@ func TestMakeMsgReply(t *testing.T) {
|
||||
transactionId := [3]byte{'1', '2', '3'}
|
||||
expectedIp := net.ParseIP("2001:db8:f00f:cafe::1")
|
||||
|
||||
builder := MakePacketBuilder(expectedServerId, 90, 100, "httpbootfileurl", "ipxebootfileurl",
|
||||
bootConfig := MakeStaticBootConfiguration("httpbootfileurl", "ipxebootfileurl")
|
||||
builder := MakePacketBuilder(expectedServerId, 90, 100, bootConfig,
|
||||
NewRandomAddressPool(net.ParseIP("2001:db8:f00f:cafe::1"), net.ParseIP("2001:db8:f00f:cafe::1"), 100))
|
||||
|
||||
msg := builder.MakeMsgReply(transactionId, expectedClientId, []byte("1234"), 0x11, expectedIp)
|
||||
@ -136,7 +139,8 @@ func TestMakeMsgReplyWithHttpClientArch(t *testing.T) {
|
||||
transactionId := [3]byte{'1', '2', '3'}
|
||||
expectedIp := net.ParseIP("2001:db8:f00f:cafe::1")
|
||||
|
||||
builder := MakePacketBuilder(expectedServerId, 90, 100, "httpbootfileurl", "ipxebootfileurl",
|
||||
bootConfig := MakeStaticBootConfiguration("httpbootfileurl", "ipxebootfileurl")
|
||||
builder := MakePacketBuilder(expectedServerId, 90, 100, bootConfig,
|
||||
NewRandomAddressPool(net.ParseIP("2001:db8:f00f:cafe::1"), net.ParseIP("2001:db8:f00f:cafe::1"), 100))
|
||||
|
||||
msg := builder.MakeMsgReply(transactionId, expectedClientId, []byte("1234"), 0x10, expectedIp)
|
||||
@ -157,7 +161,8 @@ func TestMakeMsgInformationRequestReply(t *testing.T) {
|
||||
expectedServerId := []byte("serverid")
|
||||
transactionId := [3]byte{'1', '2', '3'}
|
||||
|
||||
builder := MakePacketBuilder(expectedServerId, 90, 100, "httpbootfileurl", "ipxebootfileurl",
|
||||
bootConfig := MakeStaticBootConfiguration("httpbootfileurl", "ipxebootfileurl")
|
||||
builder := MakePacketBuilder(expectedServerId, 90, 100, bootConfig,
|
||||
NewRandomAddressPool(net.ParseIP("2001:db8:f00f:cafe::1"), net.ParseIP("2001:db8:f00f:cafe::1"), 100))
|
||||
|
||||
msg := builder.MakeMsgInformationRequestReply(transactionId, expectedClientId, 0x11)
|
||||
@ -202,7 +207,8 @@ func TestMakeMsgInformationRequestReplyWithHttpClientArch(t *testing.T) {
|
||||
expectedServerId := []byte("serverid")
|
||||
transactionId := [3]byte{'1', '2', '3'}
|
||||
|
||||
builder := MakePacketBuilder(expectedServerId, 90, 100, "httpbootfileurl", "ipxebootfileurl",
|
||||
bootConfig := MakeStaticBootConfiguration("httpbootfileurl", "ipxebootfileurl")
|
||||
builder := MakePacketBuilder(expectedServerId, 90, 100, bootConfig,
|
||||
NewRandomAddressPool(net.ParseIP("2001:db8:f00f:cafe::1"), net.ParseIP("2001:db8:f00f:cafe::1"), 100))
|
||||
|
||||
msg := builder.MakeMsgInformationRequestReply(transactionId, expectedClientId, 0x10)
|
||||
@ -223,7 +229,8 @@ func TestMakeMsgReleaseReply(t *testing.T) {
|
||||
expectedServerId := []byte("serverid")
|
||||
transactionId := [3]byte{'1', '2', '3'}
|
||||
|
||||
builder := MakePacketBuilder(expectedServerId, 90, 100, "httpbootfileurl", "ipxebootfileurl",
|
||||
bootConfig := MakeStaticBootConfiguration("httpbootfileurl", "ipxebootfileurl")
|
||||
builder := MakePacketBuilder(expectedServerId, 90, 100, bootConfig,
|
||||
NewRandomAddressPool(net.ParseIP("2001:db8:f00f:cafe::1"), net.ParseIP("2001:db8:f00f:cafe::1"), 100))
|
||||
|
||||
msg := builder.MakeMsgReleaseReply(transactionId, expectedClientId)
|
||||
@ -258,6 +265,33 @@ func TestMakeMsgReleaseReply(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
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})
|
||||
if string(expectedLLAddress) != string(llAddress) {
|
||||
t.Fatalf("Expected ll address %x, got: %x", expectedLLAddress, llAddress)
|
||||
}
|
||||
}
|
||||
|
||||
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})
|
||||
if string(expectedId) != string(id) {
|
||||
t.Fatalf("Expected id %x, got: %x", expectedId, id)
|
||||
}
|
||||
}
|
||||
|
||||
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})
|
||||
if string(expectedLLAddress) != string(llAddress) {
|
||||
t.Fatalf("Expected ll address %x, got: %x", expectedLLAddress, llAddress)
|
||||
}
|
||||
}
|
||||
|
||||
func TestShouldDiscardSolicitWithoutBootfileUrlOption(t *testing.T) {
|
||||
clientId := []byte("clientid")
|
||||
options := make(Options)
|
||||
@ -343,6 +377,7 @@ func TestShouldDiscardRequestWithWrongServerId(t *testing.T) {
|
||||
t.Fatalf("Should discard request packet with wrong server id option, but didn't")
|
||||
}
|
||||
}
|
||||
|
||||
func MakeOptionRequestOptions(options []uint16) *Option {
|
||||
value := make([]byte, len(options)*2)
|
||||
for i, option := range(options) {
|
||||
|
||||
@ -91,10 +91,10 @@ func (p *RandomAddressPool) ReserveAddress(clientId, interfaceId []byte) *Identi
|
||||
newIp := big.NewInt(0).Add(p.poolStartAddress, big.NewInt(0).SetUint64(hostOffset))
|
||||
_, exists := p.usedIps[newIp.Uint64()]; if !exists {
|
||||
timeNow := p.timeNow()
|
||||
to_ret := &IdentityAssociation{clientId: clientId,
|
||||
interfaceId: interfaceId,
|
||||
ipAddress: newIp.Bytes(),
|
||||
createdAt: timeNow }
|
||||
to_ret := &IdentityAssociation{ClientId: clientId,
|
||||
InterfaceId: interfaceId,
|
||||
IpAddress: newIp.Bytes(),
|
||||
CreatedAt: timeNow }
|
||||
p.identityAssociations[clientIdHash] = to_ret
|
||||
p.usedIps[newIp.Uint64()] = struct{}{}
|
||||
p.identityAssociationExpirations.Push(&AssociationExpiration{expiresAt: p.calculateAssociationExpiration(timeNow), ia: to_ret})
|
||||
@ -113,7 +113,7 @@ func (p *RandomAddressPool) ReleaseAddress(clientId, interfaceId []byte) {
|
||||
p.lock <- 1
|
||||
return
|
||||
}
|
||||
delete(p.usedIps, big.NewInt(0).SetBytes(association.ipAddress).Uint64())
|
||||
delete(p.usedIps, big.NewInt(0).SetBytes(association.IpAddress).Uint64())
|
||||
delete(p.identityAssociations, p.calculateIaIdHash(clientId, interfaceId))
|
||||
p.lock <- 1
|
||||
}
|
||||
@ -125,8 +125,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())
|
||||
}
|
||||
p.lock <- 1
|
||||
}
|
||||
|
||||
@ -20,20 +20,20 @@ func TestReserveAddress(t *testing.T) {
|
||||
if ia == nil {
|
||||
t.Fatalf("Expected a non-nil identity association")
|
||||
}
|
||||
if string(ia.ipAddress) != string(expectedIp) {
|
||||
t.Fatalf("Expected ip: %v, but got: %v", expectedIp, ia.ipAddress)
|
||||
if string(ia.IpAddress) != string(expectedIp) {
|
||||
t.Fatalf("Expected ip: %v, but got: %v", expectedIp, ia.IpAddress)
|
||||
}
|
||||
if string(ia.clientId) != string(expectedClientId) {
|
||||
t.Fatalf("Expected client id: %v, but got: %v", expectedClientId, ia.clientId)
|
||||
if string(ia.ClientId) != string(expectedClientId) {
|
||||
t.Fatalf("Expected client id: %v, but got: %v", expectedClientId, ia.ClientId)
|
||||
}
|
||||
if string(ia.interfaceId) != string(expectedIaId) {
|
||||
t.Fatalf("Expected interface id: %v, but got: %v", expectedIaId, ia.interfaceId)
|
||||
if string(ia.InterfaceId) != string(expectedIaId) {
|
||||
t.Fatalf("Expected interface id: %v, but got: %v", expectedIaId, ia.InterfaceId)
|
||||
}
|
||||
if ia.createdAt != expectedTime {
|
||||
t.Fatalf("Expected creation time: %v, but got: %v", expectedTime, ia.createdAt)
|
||||
if ia.CreatedAt != expectedTime {
|
||||
t.Fatalf("Expected creation time: %v, but got: %v", expectedTime, ia.CreatedAt)
|
||||
}
|
||||
if ia.createdAt != expectedTime {
|
||||
t.Fatalf("Expected creation time: %v, but got: %v", expectedTime, ia.createdAt)
|
||||
if ia.CreatedAt != expectedTime {
|
||||
t.Fatalf("Expected creation time: %v, but got: %v", expectedTime, ia.CreatedAt)
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,8 +53,8 @@ func TestReserveAddressUpdatesAddressPool(t *testing.T) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,7 +104,7 @@ func TestReserveAddressReturnsExistingAssociation(t *testing.T) {
|
||||
firstAssociation := pool.ReserveAddress(expectedClientId, expectedIaId)
|
||||
secondAssociation := pool.ReserveAddress(expectedClientId, expectedIaId)
|
||||
|
||||
if string(firstAssociation.ipAddress) != string(secondAssociation.ipAddress) {
|
||||
if string(firstAssociation.IpAddress) != string(secondAssociation.IpAddress) {
|
||||
t.Fatal("Expected return of the same ip address on both invocations")
|
||||
}
|
||||
}
|
||||
@ -122,6 +122,6 @@ func TestReleaseAddress(t *testing.T) {
|
||||
pool.ReleaseAddress(expectedClientId, 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.ipAddress)
|
||||
t.Fatalf("identity association for %v should've been removed, but is still available", a.IpAddress)
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,8 +2,8 @@ package cli
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"go.universe.tf/netboot/pixiecore"
|
||||
"fmt"
|
||||
"go.universe.tf/netboot/pixiecorev6"
|
||||
)
|
||||
|
||||
var bootIPv6Cmd = &cobra.Command{
|
||||
@ -23,7 +23,7 @@ var bootIPv6Cmd = &cobra.Command{
|
||||
fatalf("Error reading flag: %s", err)
|
||||
}
|
||||
|
||||
s := pixiecore.NewServerV6()
|
||||
s := pixiecorev6.NewServerV6()
|
||||
|
||||
if addr == "" {
|
||||
fatalf("Please specify address to listen on")
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
package pixiecore
|
||||
package pixiecorev6
|
||||
|
||||
import (
|
||||
"go.universe.tf/netboot/dhcp6"
|
||||
@ -1,4 +1,4 @@
|
||||
package pixiecore
|
||||
package pixiecorev6
|
||||
|
||||
import (
|
||||
"go.universe.tf/netboot/dhcp6"
|
||||
@ -19,7 +19,6 @@ type ServerV6 struct {
|
||||
errs chan error
|
||||
|
||||
eventsMu sync.Mutex
|
||||
events map[string][]machineEvent
|
||||
|
||||
Log func(subsystem, msg string)
|
||||
Debug func(subsystem, msg string)
|
||||
@ -45,7 +44,6 @@ func (s *ServerV6) Serve() error {
|
||||
|
||||
s.log("dhcp", "new connection...")
|
||||
|
||||
s.events = make(map[string][]machineEvent)
|
||||
// 5 buffer slots, one for each goroutine, plus one for
|
||||
// Shutdown(). We only ever pull the first error out, but shutdown
|
||||
// will likely generate some spurious errors from the other
|
||||
@ -57,9 +55,9 @@ func (s *ServerV6) Serve() error {
|
||||
s.SetDUID(dhcp.SourceHardwareAddress())
|
||||
|
||||
addressPool := dhcp6.NewRandomAddressPool(net.ParseIP("2001:db8:f00f:cafe::10"), net.ParseIP("2001:db8:f00f:cafe::100"), 1850)
|
||||
packetBuilder := dhcp6.MakePacketBuilder(s.Duid, 1800, 1850,
|
||||
"http://[2001:db8:f00f:cafe::4]/bootx64.efi",
|
||||
"http://[2001:db8:f00f:cafe::4]/script.ipxe", addressPool)
|
||||
// bootConfiguration := dhcp6.MakeStaticBootConfiguration("http://[2001:db8:f00f:cafe::4]/bootx64.efi", "http://[2001:db8:f00f:cafe::4]/script.ipxe")
|
||||
bootConfiguration := dhcp6.MakeApiBootConfiguration("http://[2001:db8:f00f:cafe::4]:8888/", 10 *time.Second)
|
||||
packetBuilder := dhcp6.MakePacketBuilder(s.Duid, 1800, 1850, bootConfiguration, addressPool)
|
||||
|
||||
go func() { s.errs <- s.serveDHCP(dhcp, packetBuilder) }()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user