mirror of
https://github.com/danderson/netboot.git
synced 2025-10-16 10:01:20 +02:00
added support for generation of "dns servers" option
This commit is contained in:
parent
b78d515ee1
commit
6c11f1e722
@ -20,10 +20,6 @@ import (
|
|||||||
"go.universe.tf/netboot/third_party/ipxe"
|
"go.universe.tf/netboot/third_party/ipxe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// qemu-system-x86_64 -L . --bios /usr/share/edk2-firmware/ipv6/OVMF.fd -netdev bridge,br=br1,id=net0 -device virtio-net-pci,netdev=net0
|
|
||||||
// sudo ./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
|
|
||||||
// sudo ./pixiecore ipv6api --listen-addr=2001:db8:f00f:cafe::4 --api-request-url=http://[2001:db8:f00f:cafe::4]:8888
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
cli.Ipxe[pixiecore.FirmwareX86PC] = ipxe.MustAsset("undionly.kpxe")
|
cli.Ipxe[pixiecore.FirmwareX86PC] = ipxe.MustAsset("undionly.kpxe")
|
||||||
cli.Ipxe[pixiecore.FirmwareEFI32] = ipxe.MustAsset("ipxe-i386.efi")
|
cli.Ipxe[pixiecore.FirmwareEFI32] = ipxe.MustAsset("ipxe-i386.efi")
|
||||||
|
@ -7,28 +7,31 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"net"
|
||||||
)
|
)
|
||||||
|
|
||||||
type BootConfiguration interface {
|
type BootConfiguration interface {
|
||||||
GetBootUrl(id []byte, clientArchType uint16) ([]byte, error)
|
GetBootUrl(id []byte, clientArchType uint16) ([]byte, error)
|
||||||
GetPreference() []byte
|
GetPreference() []byte
|
||||||
GetRecursiveDns() []byte
|
GetRecursiveDns() []net.IP
|
||||||
}
|
}
|
||||||
|
|
||||||
type StaticBootConfiguration struct {
|
type StaticBootConfiguration struct {
|
||||||
HttpBootUrl []byte
|
HttpBootUrl []byte
|
||||||
IPxeBootUrl []byte
|
IPxeBootUrl []byte
|
||||||
RecursiveDns []byte
|
RecursiveDns []net.IP
|
||||||
Preference []byte
|
Preference []byte
|
||||||
UsePreference bool
|
UsePreference bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeStaticBootConfiguration(httpBootUrl, ipxeBootUrl string, preference uint8, usePreference bool) *StaticBootConfiguration {
|
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 {
|
if usePreference {
|
||||||
ret.Preference = make([]byte, 1)
|
ret.Preference = make([]byte, 1)
|
||||||
ret.Preference[0] = byte(preference)
|
ret.Preference[0] = byte(preference)
|
||||||
}
|
}
|
||||||
|
ret.RecursiveDns = dnsServerAddresses
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,19 +46,20 @@ func (bc *StaticBootConfiguration) GetPreference() []byte {
|
|||||||
return bc.Preference
|
return bc.Preference
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bc *StaticBootConfiguration) GetRecursiveDns() []byte {
|
func (bc *StaticBootConfiguration) GetRecursiveDns() []net.IP {
|
||||||
return bc.RecursiveDns
|
return bc.RecursiveDns
|
||||||
}
|
}
|
||||||
|
|
||||||
type ApiBootConfiguration struct {
|
type ApiBootConfiguration struct {
|
||||||
client *http.Client
|
client *http.Client
|
||||||
urlPrefix string
|
urlPrefix string
|
||||||
RecursiveDns []byte
|
RecursiveDns []net.IP
|
||||||
Preference []byte
|
Preference []byte
|
||||||
UsePreference bool
|
UsePreference bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeApiBootConfiguration(url string, timeout time.Duration, preference uint8, usePreference bool) *ApiBootConfiguration {
|
func MakeApiBootConfiguration(url string, timeout time.Duration, preference uint8, usePreference bool,
|
||||||
|
dnsServerAddresses []net.IP) *ApiBootConfiguration {
|
||||||
if !strings.HasSuffix(url, "/") {
|
if !strings.HasSuffix(url, "/") {
|
||||||
url += "/"
|
url += "/"
|
||||||
}
|
}
|
||||||
@ -68,6 +72,7 @@ func MakeApiBootConfiguration(url string, timeout time.Duration, preference uint
|
|||||||
ret.Preference = make([]byte, 1)
|
ret.Preference = make([]byte, 1)
|
||||||
ret.Preference[0] = byte(preference)
|
ret.Preference[0] = byte(preference)
|
||||||
}
|
}
|
||||||
|
ret.RecursiveDns = dnsServerAddresses
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
@ -110,6 +115,6 @@ func (bc *ApiBootConfiguration) GetPreference() []byte {
|
|||||||
return bc.Preference
|
return bc.Preference
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bc *ApiBootConfiguration) GetRecursiveDns() []byte {
|
func (bc *ApiBootConfiguration) GetRecursiveDns() []net.IP {
|
||||||
return bc.RecursiveDns
|
return bc.RecursiveDns
|
||||||
}
|
}
|
||||||
|
@ -158,6 +158,14 @@ func MakeStatusOption(statusCode uint16, message string) *Option {
|
|||||||
return MakeOption(OptStatusCode, value)
|
return MakeOption(OptStatusCode, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MakeDNSServersOption(addresses []net.IP) *Option {
|
||||||
|
value := make([]byte, 16*len(addresses))
|
||||||
|
for i, dnsAddress := range addresses {
|
||||||
|
copy(value[i*16:], dnsAddress)
|
||||||
|
}
|
||||||
|
return MakeOption(OptRecursiveDns, value)
|
||||||
|
}
|
||||||
|
|
||||||
func (o Options) Marshal() ([]byte, error) {
|
func (o Options) Marshal() ([]byte, error) {
|
||||||
buffer := bytes.NewBuffer(make([]byte, 0, 1446))
|
buffer := bytes.NewBuffer(make([]byte, 0, 1446))
|
||||||
for _, multipleOptions := range(o) {
|
for _, multipleOptions := range(o) {
|
||||||
|
@ -102,3 +102,22 @@ func TestUnmarshalFailsIfOROLengthIsOdd(t *testing.T) {
|
|||||||
t.Fatalf("Parsing options should fail: option request for options has odd length.")
|
t.Fatalf("Parsing options should fail: option request for options has odd length.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMakeDNSServersOption(t *testing.T) {
|
||||||
|
expectedAddress1 := net.ParseIP("2001:db8:f00f:cafe::99")
|
||||||
|
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.Length != 32 {
|
||||||
|
t.Fatalf("Expected length 32 bytes, got %d", dnsServersOption.Length)
|
||||||
|
}
|
||||||
|
if string(dnsServersOption.Value[0:16]) != string(expectedAddress1) {
|
||||||
|
t.Fatalf("Expected dns server address %v, got %v", expectedAddress1, net.IP(dnsServersOption.Value[0:16]))
|
||||||
|
}
|
||||||
|
if string(dnsServersOption.Value[16:]) != string(expectedAddress2) {
|
||||||
|
t.Fatalf("Expected dns server address %v, got %v", expectedAddress2, net.IP(dnsServersOption.Value[16:]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -3,6 +3,7 @@ package dhcp6
|
|||||||
import (
|
import (
|
||||||
"hash/fnv"
|
"hash/fnv"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"net"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PacketBuilder struct {
|
type PacketBuilder struct {
|
||||||
@ -27,7 +28,7 @@ func (b *PacketBuilder) BuildResponse(in *Packet, configuration BootConfiguratio
|
|||||||
return b.MakeMsgAdvertiseWithNoAddrsAvailable(in.TransactionID, in.Options.ClientId(), err), err
|
return b.MakeMsgAdvertiseWithNoAddrsAvailable(in.TransactionID, in.Options.ClientId(), err), err
|
||||||
}
|
}
|
||||||
return b.MakeMsgAdvertise(in.TransactionID, in.Options.ClientId(),
|
return b.MakeMsgAdvertise(in.TransactionID, in.Options.ClientId(),
|
||||||
in.Options.ClientArchType(), associations, bootFileUrl, configuration.GetPreference()), nil
|
in.Options.ClientArchType(), associations, bootFileUrl, configuration.GetPreference(), configuration.GetRecursiveDns()), nil
|
||||||
case MsgRequest:
|
case MsgRequest:
|
||||||
bootFileUrl, err := configuration.GetBootUrl(b.ExtractLLAddressOrId(in.Options.ClientId()), in.Options.ClientArchType())
|
bootFileUrl, err := configuration.GetBootUrl(b.ExtractLLAddressOrId(in.Options.ClientId()), in.Options.ClientArchType())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -35,14 +36,15 @@ func (b *PacketBuilder) BuildResponse(in *Packet, configuration BootConfiguratio
|
|||||||
}
|
}
|
||||||
associations, err := addresses.ReserveAddresses(in.Options.ClientId(), in.Options.IaNaIds())
|
associations, err := addresses.ReserveAddresses(in.Options.ClientId(), in.Options.IaNaIds())
|
||||||
return b.MakeMsgReply(in.TransactionID, in.Options.ClientId(),
|
return b.MakeMsgReply(in.TransactionID, in.Options.ClientId(),
|
||||||
in.Options.ClientArchType(), associations, iasWithoutAddesses(associations, in.Options.IaNaIds()), bootFileUrl, err), err
|
in.Options.ClientArchType(), associations, iasWithoutAddesses(associations, in.Options.IaNaIds()), bootFileUrl,
|
||||||
|
configuration.GetRecursiveDns(), err), err
|
||||||
case MsgInformationRequest:
|
case MsgInformationRequest:
|
||||||
bootFileUrl, err := configuration.GetBootUrl(b.ExtractLLAddressOrId(in.Options.ClientId()), in.Options.ClientArchType())
|
bootFileUrl, err := configuration.GetBootUrl(b.ExtractLLAddressOrId(in.Options.ClientId()), in.Options.ClientArchType())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return b.MakeMsgInformationRequestReply(in.TransactionID, in.Options.ClientId(),
|
return b.MakeMsgInformationRequestReply(in.TransactionID, in.Options.ClientId(),
|
||||||
in.Options.ClientArchType(), bootFileUrl), nil
|
in.Options.ClientArchType(), bootFileUrl, configuration.GetRecursiveDns()), nil
|
||||||
case MsgRelease:
|
case MsgRelease:
|
||||||
addresses.ReleaseAddresses(in.Options.ClientId(), in.Options.IaNaIds())
|
addresses.ReleaseAddresses(in.Options.ClientId(), in.Options.IaNaIds())
|
||||||
return b.MakeMsgReleaseReply(in.TransactionID, in.Options.ClientId()), nil
|
return b.MakeMsgReleaseReply(in.TransactionID, in.Options.ClientId()), nil
|
||||||
@ -52,7 +54,7 @@ func (b *PacketBuilder) BuildResponse(in *Packet, configuration BootConfiguratio
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *PacketBuilder) MakeMsgAdvertise(transactionId [3]byte, clientId []byte, clientArchType uint16,
|
func (b *PacketBuilder) MakeMsgAdvertise(transactionId [3]byte, clientId []byte, clientArchType uint16,
|
||||||
associations []*IdentityAssociation, bootFileUrl, preference []byte) *Packet {
|
associations []*IdentityAssociation, bootFileUrl, preference []byte, dnsServers []net.IP) *Packet {
|
||||||
ret_options := make(Options)
|
ret_options := make(Options)
|
||||||
ret_options.AddOption(MakeOption(OptClientId, clientId))
|
ret_options.AddOption(MakeOption(OptClientId, clientId))
|
||||||
for _, association := range(associations) {
|
for _, association := range(associations) {
|
||||||
@ -65,15 +67,13 @@ func (b *PacketBuilder) MakeMsgAdvertise(transactionId [3]byte, clientId []byte,
|
|||||||
}
|
}
|
||||||
ret_options.AddOption(MakeOption(OptBootfileUrl, bootFileUrl))
|
ret_options.AddOption(MakeOption(OptBootfileUrl, bootFileUrl))
|
||||||
if preference != nil {ret_options.AddOption(MakeOption(OptPreference, preference))}
|
if preference != nil {ret_options.AddOption(MakeOption(OptPreference, preference))}
|
||||||
|
ret_options.AddOption(MakeDNSServersOption(dnsServers))
|
||||||
//ret_options.AddOption(OptRecursiveDns, net.ParseIP("2001:db8:f00f:cafe::1"))
|
|
||||||
//ret_options.AddOption(OptBootfileParam, []byte("http://")
|
|
||||||
|
|
||||||
return &Packet{Type: MsgAdvertise, TransactionID: transactionId, Options: ret_options}
|
return &Packet{Type: MsgAdvertise, TransactionID: transactionId, Options: ret_options}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *PacketBuilder) MakeMsgReply(transactionId [3]byte, clientId []byte, clientArchType uint16,
|
func (b *PacketBuilder) MakeMsgReply(transactionId [3]byte, clientId []byte, clientArchType uint16,
|
||||||
associations []*IdentityAssociation, iasWithoutAddresses [][]byte, bootFileUrl []byte, err error) *Packet {
|
associations []*IdentityAssociation, iasWithoutAddresses [][]byte, bootFileUrl []byte, dnsServers []net.IP, err error) *Packet {
|
||||||
ret_options := make(Options)
|
ret_options := make(Options)
|
||||||
ret_options.AddOption(MakeOption(OptClientId, clientId))
|
ret_options.AddOption(MakeOption(OptClientId, clientId))
|
||||||
for _, association := range(associations) {
|
for _, association := range(associations) {
|
||||||
@ -89,12 +89,13 @@ func (b *PacketBuilder) MakeMsgReply(transactionId [3]byte, clientId []byte, cli
|
|||||||
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(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))
|
ret_options.AddOption(MakeOption(OptBootfileUrl, bootFileUrl))
|
||||||
|
ret_options.AddOption(MakeDNSServersOption(dnsServers))
|
||||||
|
|
||||||
return &Packet{Type: MsgReply, TransactionID: transactionId, Options: ret_options}
|
return &Packet{Type: MsgReply, TransactionID: transactionId, Options: ret_options}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *PacketBuilder) MakeMsgInformationRequestReply(transactionId [3]byte, clientId []byte, clientArchType uint16,
|
func (b *PacketBuilder) MakeMsgInformationRequestReply(transactionId [3]byte, clientId []byte, clientArchType uint16,
|
||||||
bootFileUrl []byte) *Packet {
|
bootFileUrl []byte, dnsServers []net.IP) *Packet {
|
||||||
ret_options := make(Options)
|
ret_options := make(Options)
|
||||||
ret_options.AddOption(MakeOption(OptClientId, clientId))
|
ret_options.AddOption(MakeOption(OptClientId, clientId))
|
||||||
ret_options.AddOption(MakeOption(OptServerId, b.ServerDuid))
|
ret_options.AddOption(MakeOption(OptServerId, b.ServerDuid))
|
||||||
@ -102,6 +103,7 @@ func (b *PacketBuilder) MakeMsgInformationRequestReply(transactionId [3]byte, cl
|
|||||||
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(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))
|
ret_options.AddOption(MakeOption(OptBootfileUrl, bootFileUrl))
|
||||||
|
ret_options.AddOption(MakeDNSServersOption(dnsServers))
|
||||||
|
|
||||||
return &Packet{Type: MsgReply, TransactionID: transactionId, Options: ret_options}
|
return &Packet{Type: MsgReply, TransactionID: transactionId, Options: ret_options}
|
||||||
}
|
}
|
||||||
|
@ -14,12 +14,13 @@ func TestMakeMsgAdvertise(t *testing.T) {
|
|||||||
transactionId := [3]byte{'1', '2', '3'}
|
transactionId := [3]byte{'1', '2', '3'}
|
||||||
expectedIp := net.ParseIP("2001:db8:f00f:cafe::1")
|
expectedIp := net.ParseIP("2001:db8:f00f:cafe::1")
|
||||||
expectedBootFileUrl := []byte("http://bootfileurl")
|
expectedBootFileUrl := []byte("http://bootfileurl")
|
||||||
|
expectedDnsServerIp := net.ParseIP("2001:db8:f00f:cafe::99")
|
||||||
identityAssociation := &IdentityAssociation{IpAddress: expectedIp, InterfaceId: expectedInterfaceId}
|
identityAssociation := &IdentityAssociation{IpAddress: expectedIp, InterfaceId: expectedInterfaceId}
|
||||||
|
|
||||||
builder := MakePacketBuilder(expectedServerId, 90, 100)
|
builder := MakePacketBuilder(expectedServerId, 90, 100)
|
||||||
|
|
||||||
msg := builder.MakeMsgAdvertise(transactionId, expectedClientId, 0x11, []*IdentityAssociation{identityAssociation},
|
msg := builder.MakeMsgAdvertise(transactionId, expectedClientId, 0x11, []*IdentityAssociation{identityAssociation},
|
||||||
expectedBootFileUrl, nil)
|
expectedBootFileUrl, nil, []net.IP{expectedDnsServerIp})
|
||||||
|
|
||||||
if msg.Type != MsgAdvertise {
|
if msg.Type != MsgAdvertise {
|
||||||
t.Fatalf("Expected message type %d, got %d", MsgAdvertise, msg.Type)
|
t.Fatalf("Expected message type %d, got %d", MsgAdvertise, msg.Type)
|
||||||
@ -70,7 +71,7 @@ func TestShouldSetPreferenceOptionWhenSpecified(t *testing.T) {
|
|||||||
|
|
||||||
expectedPreference := []byte{128}
|
expectedPreference := []byte{128}
|
||||||
msg := builder.MakeMsgAdvertise([3]byte{'t', 'i', 'd'}, []byte("clientid"), 0x11,
|
msg := builder.MakeMsgAdvertise([3]byte{'t', 'i', 'd'}, []byte("clientid"), 0x11,
|
||||||
[]*IdentityAssociation{identityAssociation}, []byte("http://bootfileurl"), expectedPreference)
|
[]*IdentityAssociation{identityAssociation}, []byte("http://bootfileurl"), expectedPreference, []net.IP{})
|
||||||
|
|
||||||
preferenceOption := msg.Options[OptPreference]
|
preferenceOption := msg.Options[OptPreference]
|
||||||
if preferenceOption == nil {
|
if preferenceOption == nil {
|
||||||
@ -92,7 +93,7 @@ func TestMakeMsgAdvertiseWithHttpClientArch(t *testing.T) {
|
|||||||
builder := MakePacketBuilder(expectedServerId, 90, 100)
|
builder := MakePacketBuilder(expectedServerId, 90, 100)
|
||||||
|
|
||||||
msg := builder.MakeMsgAdvertise(transactionId, expectedClientId, 0x10, []*IdentityAssociation{identityAssociation},
|
msg := builder.MakeMsgAdvertise(transactionId, expectedClientId, 0x10, []*IdentityAssociation{identityAssociation},
|
||||||
expectedBootFileUrl, nil)
|
expectedBootFileUrl, nil, []net.IP{})
|
||||||
|
|
||||||
vendorClassOption := msg.Options[OptVendorClass]
|
vendorClassOption := msg.Options[OptVendorClass]
|
||||||
if vendorClassOption == nil {
|
if vendorClassOption == nil {
|
||||||
@ -158,12 +159,13 @@ func TestMakeMsgReply(t *testing.T) {
|
|||||||
transactionId := [3]byte{'1', '2', '3'}
|
transactionId := [3]byte{'1', '2', '3'}
|
||||||
expectedIp := net.ParseIP("2001:db8:f00f:cafe::1")
|
expectedIp := net.ParseIP("2001:db8:f00f:cafe::1")
|
||||||
expectedBootFileUrl := []byte("http://bootfileurl")
|
expectedBootFileUrl := []byte("http://bootfileurl")
|
||||||
|
expectedDnsServerIp := net.ParseIP("2001:db8:f00f:cafe::99")
|
||||||
identityAssociation := &IdentityAssociation{IpAddress: expectedIp, InterfaceId: []byte("id-1")}
|
identityAssociation := &IdentityAssociation{IpAddress: expectedIp, InterfaceId: []byte("id-1")}
|
||||||
|
|
||||||
builder := MakePacketBuilder(expectedServerId, 90, 100)
|
builder := MakePacketBuilder(expectedServerId, 90, 100)
|
||||||
|
|
||||||
msg := builder.MakeMsgReply(transactionId, expectedClientId, 0x11, []*IdentityAssociation{identityAssociation},
|
msg := builder.MakeMsgReply(transactionId, expectedClientId, 0x11, []*IdentityAssociation{identityAssociation},
|
||||||
make([][]byte, 0), expectedBootFileUrl, nil)
|
make([][]byte, 0), expectedBootFileUrl, []net.IP{expectedDnsServerIp}, nil)
|
||||||
|
|
||||||
if msg.Type != MsgReply {
|
if msg.Type != MsgReply {
|
||||||
t.Fatalf("Expected message type %d, got %d", MsgAdvertise, msg.Type)
|
t.Fatalf("Expected message type %d, got %d", MsgAdvertise, msg.Type)
|
||||||
@ -220,7 +222,7 @@ func TestMakeMsgReplyWithHttpClientArch(t *testing.T) {
|
|||||||
|
|
||||||
msg := builder.MakeMsgReply(transactionId, expectedClientId, 0x10,
|
msg := builder.MakeMsgReply(transactionId, expectedClientId, 0x10,
|
||||||
[]*IdentityAssociation{identityAssociation}, make([][]byte, 0),
|
[]*IdentityAssociation{identityAssociation}, make([][]byte, 0),
|
||||||
expectedBootFileUrl, nil)
|
expectedBootFileUrl, []net.IP{}, nil)
|
||||||
|
|
||||||
vendorClassOption := msg.Options[OptVendorClass]
|
vendorClassOption := msg.Options[OptVendorClass]
|
||||||
if vendorClassOption == nil {
|
if vendorClassOption == nil {
|
||||||
@ -248,7 +250,7 @@ func TestMakeMsgReplyWithNoAddrsAvailable(t *testing.T) {
|
|||||||
builder := MakePacketBuilder(expectedServerId, 90, 100)
|
builder := MakePacketBuilder(expectedServerId, 90, 100)
|
||||||
|
|
||||||
msg := builder.MakeMsgReply(transactionId, expectedClientId, 0x10,
|
msg := builder.MakeMsgReply(transactionId, expectedClientId, 0x10,
|
||||||
[]*IdentityAssociation{identityAssociation}, [][]byte{[]byte("id-2")}, expectedBootFileUrl,
|
[]*IdentityAssociation{identityAssociation}, [][]byte{[]byte("id-2")}, expectedBootFileUrl, []net.IP{},
|
||||||
fmt.Errorf(expectedErrorMessage))
|
fmt.Errorf(expectedErrorMessage))
|
||||||
|
|
||||||
iaNaOption := msg.Options[OptIaNa]
|
iaNaOption := msg.Options[OptIaNa]
|
||||||
@ -295,10 +297,12 @@ func TestMakeMsgInformationRequestReply(t *testing.T) {
|
|||||||
expectedServerId := []byte("serverid")
|
expectedServerId := []byte("serverid")
|
||||||
transactionId := [3]byte{'1', '2', '3'}
|
transactionId := [3]byte{'1', '2', '3'}
|
||||||
expectedBootFileUrl := []byte("http://bootfileurl")
|
expectedBootFileUrl := []byte("http://bootfileurl")
|
||||||
|
expectedDnsServerIp := net.ParseIP("2001:db8:f00f:cafe::99")
|
||||||
|
|
||||||
builder := MakePacketBuilder(expectedServerId, 90, 100)
|
builder := MakePacketBuilder(expectedServerId, 90, 100)
|
||||||
|
|
||||||
msg := builder.MakeMsgInformationRequestReply(transactionId, expectedClientId, 0x11, expectedBootFileUrl)
|
msg := builder.MakeMsgInformationRequestReply(transactionId, expectedClientId, 0x11,
|
||||||
|
expectedBootFileUrl, []net.IP{expectedDnsServerIp})
|
||||||
|
|
||||||
if msg.Type != MsgReply {
|
if msg.Type != MsgReply {
|
||||||
t.Fatalf("Expected message type %d, got %d", MsgAdvertise, msg.Type)
|
t.Fatalf("Expected message type %d, got %d", MsgAdvertise, msg.Type)
|
||||||
@ -346,7 +350,8 @@ func TestMakeMsgInformationRequestReplyWithHttpClientArch(t *testing.T) {
|
|||||||
|
|
||||||
builder := MakePacketBuilder(expectedServerId, 90, 100)
|
builder := MakePacketBuilder(expectedServerId, 90, 100)
|
||||||
|
|
||||||
msg := builder.MakeMsgInformationRequestReply(transactionId, expectedClientId, 0x10, expectedBootFileUrl)
|
msg := builder.MakeMsgInformationRequestReply(transactionId, expectedClientId, 0x10,
|
||||||
|
expectedBootFileUrl, []net.IP{})
|
||||||
|
|
||||||
vendorClassOption := msg.Options[OptVendorClass]
|
vendorClassOption := msg.Options[OptVendorClass]
|
||||||
if vendorClassOption == nil {
|
if vendorClassOption == nil {
|
||||||
|
@ -6,8 +6,10 @@ import (
|
|||||||
"go.universe.tf/netboot/pixiecorev6"
|
"go.universe.tf/netboot/pixiecorev6"
|
||||||
"go.universe.tf/netboot/dhcp6"
|
"go.universe.tf/netboot/dhcp6"
|
||||||
"net"
|
"net"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 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
|
||||||
var bootIPv6Cmd = &cobra.Command{
|
var bootIPv6Cmd = &cobra.Command{
|
||||||
Use: "bootipv6",
|
Use: "bootipv6",
|
||||||
Short: "Boot a kernel and optional init ramdisks over IPv6",
|
Short: "Boot a kernel and optional init ramdisks over IPv6",
|
||||||
@ -50,7 +52,18 @@ var bootIPv6Cmd = &cobra.Command{
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf("Error reading flag: %s", err)
|
fatalf("Error reading flag: %s", err)
|
||||||
}
|
}
|
||||||
s.BootConfig = dhcp6.MakeStaticBootConfiguration(httpBootUrl, ipxeUrl, preference, cmd.Flags().Changed("preference"))
|
dnsServers, err := cmd.Flags().GetString("dns-servers")
|
||||||
|
if err != nil {
|
||||||
|
fatalf("Error reading flag: %s", err)
|
||||||
|
}
|
||||||
|
dnsServerAddresses := make([]net.IP, 0)
|
||||||
|
if cmd.Flags().Changed("dns-servers") {
|
||||||
|
for _, dnsServerAddress := range strings.Split(dnsServers, ",") {
|
||||||
|
dnsServerAddresses = append(dnsServerAddresses, net.ParseIP(dnsServerAddress))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.BootConfig = dhcp6.MakeStaticBootConfiguration(httpBootUrl, ipxeUrl, preference,
|
||||||
|
cmd.Flags().Changed("preference"), dnsServerAddresses)
|
||||||
|
|
||||||
addressPoolStart, err := cmd.Flags().GetString("address-pool-start")
|
addressPoolStart, err := cmd.Flags().GetString("address-pool-start")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -80,6 +93,7 @@ func serverv6ConfigFlags(cmd *cobra.Command) {
|
|||||||
cmd.Flags().StringP("address-pool-start", "", "2001:db8:f00f:cafe:ffff::100", "Starting ip of the address pool, e.g. 2001:db8:f00f:cafe:ffff::100")
|
cmd.Flags().StringP("address-pool-start", "", "2001:db8:f00f:cafe:ffff::100", "Starting ip of the address pool, e.g. 2001:db8:f00f:cafe:ffff::100")
|
||||||
cmd.Flags().Uint64("address-pool-size", 50, "Address pool size")
|
cmd.Flags().Uint64("address-pool-size", 50, "Address pool size")
|
||||||
cmd.Flags().Uint32("address-pool-lifetime", 1850, "Address pool ip valid lifetime in seconds")
|
cmd.Flags().Uint32("address-pool-lifetime", 1850, "Address pool ip valid lifetime in seconds")
|
||||||
|
cmd.Flags().StringP("dns-servers", "", "", "Comma separated list of one or more dns server addresses")
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -7,8 +7,11 @@ import (
|
|||||||
"go.universe.tf/netboot/dhcp6"
|
"go.universe.tf/netboot/dhcp6"
|
||||||
"time"
|
"time"
|
||||||
"net"
|
"net"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// pixiecore ipv6api --listen-addr=2001:db8:f00f:cafe::4 --api-request-url=http://[2001:db8:f00f:cafe::4]:8888
|
||||||
|
|
||||||
var ipv6ApiCmd = &cobra.Command{
|
var ipv6ApiCmd = &cobra.Command{
|
||||||
Use: "ipv6api",
|
Use: "ipv6api",
|
||||||
Short: "Boot a kernel and optional init ramdisks over IPv6 using api",
|
Short: "Boot a kernel and optional init ramdisks over IPv6 using api",
|
||||||
@ -46,7 +49,18 @@ var ipv6ApiCmd = &cobra.Command{
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf("Error reading flag: %s", err)
|
fatalf("Error reading flag: %s", err)
|
||||||
}
|
}
|
||||||
s.BootConfig = dhcp6.MakeApiBootConfiguration(apiUrl, apiTimeout, preference, cmd.Flags().Changed("preference"))
|
dnsServers, err := cmd.Flags().GetString("dns-servers")
|
||||||
|
if err != nil {
|
||||||
|
fatalf("Error reading flag: %s", err)
|
||||||
|
}
|
||||||
|
dnsServerAddresses := make([]net.IP, 0)
|
||||||
|
if cmd.Flags().Changed("dns-servers") {
|
||||||
|
for _, dnsServerAddress := range strings.Split(dnsServers, ",") {
|
||||||
|
dnsServerAddresses = append(dnsServerAddresses, net.ParseIP(dnsServerAddress))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.BootConfig = dhcp6.MakeApiBootConfiguration(apiUrl, apiTimeout, preference,
|
||||||
|
cmd.Flags().Changed("preference"), dnsServerAddresses)
|
||||||
|
|
||||||
addressPoolStart, err := cmd.Flags().GetString("address-pool-start")
|
addressPoolStart, err := cmd.Flags().GetString("address-pool-start")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -76,6 +90,7 @@ func serverv6ApiConfigFlags(cmd *cobra.Command) {
|
|||||||
cmd.Flags().StringP("address-pool-start", "", "2001:db8:f00f:cafe:ffff::100", "Starting ip of the address pool, e.g. 2001:db8:f00f:cafe:ffff::100")
|
cmd.Flags().StringP("address-pool-start", "", "2001:db8:f00f:cafe:ffff::100", "Starting ip of the address pool, e.g. 2001:db8:f00f:cafe:ffff::100")
|
||||||
cmd.Flags().Uint64("address-pool-size", 50, "Address pool size")
|
cmd.Flags().Uint64("address-pool-size", 50, "Address pool size")
|
||||||
cmd.Flags().Uint32("address-pool-lifetime", 1850, "Address pool ip address valid lifetime in seconds")
|
cmd.Flags().Uint32("address-pool-lifetime", 1850, "Address pool ip address valid lifetime in seconds")
|
||||||
|
cmd.Flags().StringP("dns-servers", "", "", "Comma separated list of one or more dns server addresses")
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user