added ipv6api command

This commit is contained in:
Dmitri Dolguikh 2017-10-23 14:40:10 -07:00 committed by Dave Anderson
parent da6402caf7
commit 2c42665a0b
7 changed files with 145 additions and 65 deletions

View File

@ -10,19 +10,19 @@ import (
) )
type BootConfiguration interface { type BootConfiguration interface {
GetBootUrl(id []byte, clientArchType uint16) (string, error) GetBootUrl(id []byte, clientArchType uint16) ([]byte, error)
} }
type StaticBootConfiguration struct { type StaticBootConfiguration struct {
HttpBootUrl string HttpBootUrl []byte
IPxeBootUrl string IPxeBootUrl []byte
} }
func MakeStaticBootConfiguration(httpBootUrl, ipxeBootUrl string) *StaticBootConfiguration { func MakeStaticBootConfiguration(httpBootUrl, ipxeBootUrl string) *StaticBootConfiguration {
return &StaticBootConfiguration{HttpBootUrl: httpBootUrl, IPxeBootUrl: ipxeBootUrl} return &StaticBootConfiguration{HttpBootUrl: []byte(httpBootUrl), IPxeBootUrl: []byte(ipxeBootUrl)}
} }
func (bc *StaticBootConfiguration) GetBootUrl(id []byte, clientArchType uint16) (string, error) { func (bc *StaticBootConfiguration) GetBootUrl(id []byte, clientArchType uint16) ([]byte, error) {
if 0x10 == clientArchType { if 0x10 == clientArchType {
return bc.HttpBootUrl, nil return bc.HttpBootUrl, nil
} }
@ -44,15 +44,15 @@ func MakeApiBootConfiguration(url string, timeout time.Duration) *ApiBootConfigu
} }
} }
func (bc *ApiBootConfiguration) GetBootUrl(id []byte, clientArchType uint16) (string, error) { func (bc *ApiBootConfiguration) GetBootUrl(id []byte, clientArchType uint16) ([]byte, error) {
reqURL := fmt.Sprintf("%s/boot/%x/%d", bc.urlPrefix, id, clientArchType) reqURL := fmt.Sprintf("%s/boot/%x/%d", bc.urlPrefix, id, clientArchType)
resp, err := bc.client.Get(reqURL) resp, err := bc.client.Get(reqURL)
if err != nil { if err != nil {
return "", err return nil, err
} }
if resp.StatusCode != http.StatusOK { if resp.StatusCode != http.StatusOK {
resp.Body.Close() resp.Body.Close()
return "", fmt.Errorf("%s: %s", reqURL, http.StatusText(resp.StatusCode)) return nil, fmt.Errorf("%s: %s", reqURL, http.StatusText(resp.StatusCode))
} }
defer resp.Body.Close() defer resp.Body.Close()
@ -60,7 +60,7 @@ func (bc *ApiBootConfiguration) GetBootUrl(id []byte, clientArchType uint16) (st
buf.ReadFrom(resp.Body) buf.ReadFrom(resp.Body)
url, _ := bc.makeURLAbsolute(buf.String()) url, _ := bc.makeURLAbsolute(buf.String())
return url, nil return []byte(url), nil
} }
func (bc *ApiBootConfiguration) makeURLAbsolute(urlStr string) (string, error) { func (bc *ApiBootConfiguration) makeURLAbsolute(urlStr string) (string, error) {

View File

@ -128,28 +128,41 @@ func ShouldDiscardInformationRequest(p *Packet, serverDuid []byte) error {
return nil return nil
} }
func (b *PacketBuilder) BuildResponse(in *Packet) *Packet { func (b *PacketBuilder) BuildResponse(in *Packet) (*Packet, error) {
switch in.Type { switch in.Type {
case MsgSolicit: case MsgSolicit:
association := b.Addresses.ReserveAddress(in.Options.ClientId(), in.Options.IaNaId()) association := b.Addresses.ReserveAddress(in.Options.ClientId(), in.Options.IaNaId())
bootFileUrl, err := b.BootFileUrl.GetBootUrl(b.ExtractLLAddressOrId(in.Options.ClientId()), in.Options.ClientArchType())
if err != nil {
return nil, err
}
return b.MakeMsgAdvertise(in.TransactionID, 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, bootFileUrl), nil
case MsgRequest: case MsgRequest:
association := b.Addresses.ReserveAddress(in.Options.ClientId(), in.Options.IaNaId()) association := b.Addresses.ReserveAddress(in.Options.ClientId(), in.Options.IaNaId())
bootFileUrl, err := b.BootFileUrl.GetBootUrl(b.ExtractLLAddressOrId(in.Options.ClientId()), in.Options.ClientArchType())
if err != nil {
return nil, err
}
return b.MakeMsgReply(in.TransactionID, 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, bootFileUrl), nil
case MsgInformationRequest: case MsgInformationRequest:
bootFileUrl, err := b.BootFileUrl.GetBootUrl(b.ExtractLLAddressOrId(in.Options.ClientId()), in.Options.ClientArchType())
if err != nil {
return nil, err
}
return b.MakeMsgInformationRequestReply(in.TransactionID, in.Options.ClientId(), return b.MakeMsgInformationRequestReply(in.TransactionID, in.Options.ClientId(),
in.Options.ClientArchType()) in.Options.ClientArchType(), bootFileUrl), nil
case MsgRelease: case MsgRelease:
b.Addresses.ReleaseAddress(in.Options.ClientId(), in.Options.IaNaId()) b.Addresses.ReleaseAddress(in.Options.ClientId(), in.Options.IaNaId())
return b.MakeMsgReleaseReply(in.TransactionID, in.Options.ClientId()) return b.MakeMsgReleaseReply(in.TransactionID, in.Options.ClientId()), nil
default: default:
return nil return nil, nil
} }
} }
func (b *PacketBuilder) MakeMsgAdvertise(transactionId [3]byte, clientId, iaId []byte, clientArchType uint16, ipAddress []byte) *Packet { func (b *PacketBuilder) MakeMsgAdvertise(transactionId [3]byte, clientId, iaId []byte, clientArchType uint16, ipAddress []byte,
bootFileUrl []byte) *Packet {
ret_options := make(Options) ret_options := make(Options)
ret_options.AddOption(MakeOption(OptClientId, clientId)) ret_options.AddOption(MakeOption(OptClientId, clientId))
ret_options.AddOption(MakeIaNaOption(iaId, b.calculateT1(), b.calculateT2(), ret_options.AddOption(MakeIaNaOption(iaId, b.calculateT1(), b.calculateT2(),
@ -158,12 +171,7 @@ func (b *PacketBuilder) MakeMsgAdvertise(transactionId [3]byte, clientId, iaId [
if 0x10 == clientArchType { // HTTPClient if 0x10 == clientArchType { // HTTPClient
ret_options.AddOption(MakeOption(OptVendorClass, []byte {0, 0, 0, 0, 0, 10, 72, 84, 84, 80, 67, 108, 105, 101, 110, 116})) // HTTPClient ret_options.AddOption(MakeOption(OptVendorClass, []byte {0, 0, 0, 0, 0, 10, 72, 84, 84, 80, 67, 108, 105, 101, 110, 116})) // HTTPClient
} }
bootfileUrl, err := b.BootFileUrl.GetBootUrl(b.ExtractLLAddressOrId(clientId), clientArchType) ret_options.AddOption(MakeOption(OptBootfileUrl, bootFileUrl))
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(OptRecursiveDns, net.ParseIP("2001:db8:f00f:cafe::1"))
//ret_options.AddOption(OptBootfileParam, []byte("http://") //ret_options.AddOption(OptBootfileParam, []byte("http://")
@ -172,7 +180,8 @@ func (b *PacketBuilder) MakeMsgAdvertise(transactionId [3]byte, clientId, iaId [
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, iaId []byte, clientArchType uint16, ipAddress []byte) *Packet { func (b *PacketBuilder) MakeMsgReply(transactionId [3]byte, clientId, iaId []byte, clientArchType uint16, ipAddress []byte,
bootFileUrl []byte) *Packet {
ret_options := make(Options) ret_options := make(Options)
ret_options.AddOption(MakeOption(OptClientId, clientId)) ret_options.AddOption(MakeOption(OptClientId, clientId))
ret_options.AddOption(MakeIaNaOption(iaId, b.calculateT1(), b.calculateT2(), ret_options.AddOption(MakeIaNaOption(iaId, b.calculateT1(), b.calculateT2(),
@ -181,27 +190,20 @@ func (b *PacketBuilder) MakeMsgReply(transactionId [3]byte, clientId, iaId []byt
if 0x10 == clientArchType { // HTTPClient if 0x10 == clientArchType { // HTTPClient
ret_options.AddOption(MakeOption(OptVendorClass, []byte {0, 0, 0, 0, 0, 10, 72, 84, 84, 80, 67, 108, 105, 101, 110, 116})) // HTTPClient ret_options.AddOption(MakeOption(OptVendorClass, []byte {0, 0, 0, 0, 0, 10, 72, 84, 84, 80, 67, 108, 105, 101, 110, 116})) // HTTPClient
} }
bootfileUrl, err := b.BootFileUrl.GetBootUrl(b.ExtractLLAddressOrId(clientId), clientArchType) ret_options.AddOption(MakeOption(OptBootfileUrl, bootFileUrl))
if err != nil {
return nil
}
ret_options.AddOption(MakeOption(OptBootfileUrl, []byte(bootfileUrl)))
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) *Packet { func (b *PacketBuilder) MakeMsgInformationRequestReply(transactionId [3]byte, clientId []byte, clientArchType uint16,
bootFileUrl []byte) *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))
if 0x10 == clientArchType { // HTTPClient if 0x10 == clientArchType { // HTTPClient
ret_options.AddOption(MakeOption(OptVendorClass, []byte {0, 0, 0, 0, 0, 10, 72, 84, 84, 80, 67, 108, 105, 101, 110, 116})) // HTTPClient ret_options.AddOption(MakeOption(OptVendorClass, []byte {0, 0, 0, 0, 0, 10, 72, 84, 84, 80, 67, 108, 105, 101, 110, 116})) // HTTPClient
} }
bootfileUrl, err := b.BootFileUrl.GetBootUrl(b.ExtractLLAddressOrId(clientId), clientArchType) ret_options.AddOption(MakeOption(OptBootfileUrl, bootFileUrl))
if err != nil {
return nil
}
ret_options.AddOption(MakeOption(OptBootfileUrl, []byte(bootfileUrl)))
return &Packet{Type: MsgReply, TransactionID: transactionId, Options: ret_options} return &Packet{Type: MsgReply, TransactionID: transactionId, Options: ret_options}
} }

View File

@ -11,12 +11,12 @@ func TestMakeMsgAdvertise(t *testing.T) {
expectedServerId := []byte("serverid") expectedServerId := []byte("serverid")
transactionId := [3]byte{'1', '2', '3'} transactionId := [3]byte{'1', '2', '3'}
expectedIp := net.ParseIP("2001:db8:f00f:cafe::1") expectedIp := net.ParseIP("2001:db8:f00f:cafe::1")
expectedBootFileUrl := []byte("http://bootfileurl")
bootConfig := MakeStaticBootConfiguration("httpbootfileurl", "ipxebootfileurl") builder := MakePacketBuilder(expectedServerId, 90, 100, nil,
builder := MakePacketBuilder(expectedServerId, 90, 100, bootConfig,
NewRandomAddressPool(net.ParseIP("2001:db8:f00f:cafe::1"), net.ParseIP("2001:db8:f00f:cafe::1"), 100)) 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) msg := builder.MakeMsgAdvertise(transactionId, expectedClientId, []byte("1234"), 0x11, expectedIp, expectedBootFileUrl)
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)
@ -51,6 +51,9 @@ func TestMakeMsgAdvertise(t *testing.T) {
if bootfileUrlOption == nil { if bootfileUrlOption == nil {
t.Fatalf("Bootfile URL option should be present") t.Fatalf("Bootfile URL option should be present")
} }
if string(expectedBootFileUrl) != string(bootfileUrlOption.Value) {
t.Fatalf("Expected bootfile URL %v, got %v", expectedBootFileUrl, bootfileUrlOption)
}
iaNaOption := msg.Options[OptIaNa] iaNaOption := msg.Options[OptIaNa]
if iaNaOption == nil { if iaNaOption == nil {
@ -63,22 +66,24 @@ func TestMakeMsgAdvertiseWithHttpClientArch(t *testing.T) {
expectedServerId := []byte("serverid") expectedServerId := []byte("serverid")
transactionId := [3]byte{'1', '2', '3'} transactionId := [3]byte{'1', '2', '3'}
expectedIp := net.ParseIP("2001:db8:f00f:cafe::1") expectedIp := net.ParseIP("2001:db8:f00f:cafe::1")
expectedBootFileUrl := []byte("http://bootfileurl")
bootConfig := MakeStaticBootConfiguration("httpbootfileurl", "ipxebootfileurl") builder := MakePacketBuilder(expectedServerId, 90, 100, nil,
builder := MakePacketBuilder(expectedServerId, 90, 100, bootConfig,
NewRandomAddressPool(net.ParseIP("2001:db8:f00f:cafe::1"), net.ParseIP("2001:db8:f00f:cafe::1"), 100)) 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) msg := builder.MakeMsgAdvertise(transactionId, expectedClientId, []byte("1234"), 0x10, expectedIp, expectedBootFileUrl)
vendorClassOption := msg.Options[OptVendorClass] vendorClassOption := msg.Options[OptVendorClass]
if vendorClassOption == nil { if vendorClassOption == nil {
t.Fatalf("Vendor class option should be present") t.Fatalf("Vendor class option should be present")
} }
bootfileUrlOption := msg.Options[OptBootfileUrl] bootfileUrlOption := msg.Options[OptBootfileUrl]
if bootfileUrlOption == nil { if bootfileUrlOption == nil {
t.Fatalf("Bootfile URL option should be present") t.Fatalf("Bootfile URL option should be present")
} }
if string(expectedBootFileUrl) != string(bootfileUrlOption.Value) {
t.Fatalf("Expected bootfile URL %v, got %v", expectedBootFileUrl, bootfileUrlOption)
}
} }
func TestMakeMsgReply(t *testing.T) { func TestMakeMsgReply(t *testing.T) {
@ -86,12 +91,12 @@ func TestMakeMsgReply(t *testing.T) {
expectedServerId := []byte("serverid") expectedServerId := []byte("serverid")
transactionId := [3]byte{'1', '2', '3'} transactionId := [3]byte{'1', '2', '3'}
expectedIp := net.ParseIP("2001:db8:f00f:cafe::1") expectedIp := net.ParseIP("2001:db8:f00f:cafe::1")
expectedBootFileUrl := []byte("http://bootfileurl")
bootConfig := MakeStaticBootConfiguration("httpbootfileurl", "ipxebootfileurl") builder := MakePacketBuilder(expectedServerId, 90, 100, nil,
builder := MakePacketBuilder(expectedServerId, 90, 100, bootConfig,
NewRandomAddressPool(net.ParseIP("2001:db8:f00f:cafe::1"), net.ParseIP("2001:db8:f00f:cafe::1"), 100)) 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) msg := builder.MakeMsgReply(transactionId, expectedClientId, []byte("1234"), 0x11, expectedIp, expectedBootFileUrl)
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)
@ -126,6 +131,9 @@ func TestMakeMsgReply(t *testing.T) {
if bootfileUrlOption == nil { if bootfileUrlOption == nil {
t.Fatalf("Bootfile URL option should be present") t.Fatalf("Bootfile URL option should be present")
} }
if string(expectedBootFileUrl) != string(bootfileUrlOption.Value) {
t.Fatalf("Expected bootfile URL %v, got %v", expectedBootFileUrl, bootfileUrlOption)
}
iaNaOption := msg.Options[OptIaNa] iaNaOption := msg.Options[OptIaNa]
if iaNaOption == nil { if iaNaOption == nil {
@ -138,12 +146,12 @@ func TestMakeMsgReplyWithHttpClientArch(t *testing.T) {
expectedServerId := []byte("serverid") expectedServerId := []byte("serverid")
transactionId := [3]byte{'1', '2', '3'} transactionId := [3]byte{'1', '2', '3'}
expectedIp := net.ParseIP("2001:db8:f00f:cafe::1") expectedIp := net.ParseIP("2001:db8:f00f:cafe::1")
expectedBootFileUrl := []byte("http://bootfileurl")
bootConfig := MakeStaticBootConfiguration("httpbootfileurl", "ipxebootfileurl") builder := MakePacketBuilder(expectedServerId, 90, 100, nil,
builder := MakePacketBuilder(expectedServerId, 90, 100, bootConfig,
NewRandomAddressPool(net.ParseIP("2001:db8:f00f:cafe::1"), net.ParseIP("2001:db8:f00f:cafe::1"), 100)) 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) msg := builder.MakeMsgReply(transactionId, expectedClientId, []byte("1234"), 0x10, expectedIp, expectedBootFileUrl)
vendorClassOption := msg.Options[OptVendorClass] vendorClassOption := msg.Options[OptVendorClass]
if vendorClassOption == nil { if vendorClassOption == nil {
@ -154,18 +162,21 @@ func TestMakeMsgReplyWithHttpClientArch(t *testing.T) {
if bootfileUrlOption == nil { if bootfileUrlOption == nil {
t.Fatalf("Bootfile URL option should be present") t.Fatalf("Bootfile URL option should be present")
} }
if string(expectedBootFileUrl) != string(bootfileUrlOption.Value) {
t.Fatalf("Expected bootfile URL %v, got %v", expectedBootFileUrl, bootfileUrlOption)
}
} }
func TestMakeMsgInformationRequestReply(t *testing.T) { func TestMakeMsgInformationRequestReply(t *testing.T) {
expectedClientId := []byte("clientid") expectedClientId := []byte("clientid")
expectedServerId := []byte("serverid") expectedServerId := []byte("serverid")
transactionId := [3]byte{'1', '2', '3'} transactionId := [3]byte{'1', '2', '3'}
expectedBootFileUrl := []byte("http://bootfileurl")
bootConfig := MakeStaticBootConfiguration("httpbootfileurl", "ipxebootfileurl") builder := MakePacketBuilder(expectedServerId, 90, 100, nil,
builder := MakePacketBuilder(expectedServerId, 90, 100, bootConfig,
NewRandomAddressPool(net.ParseIP("2001:db8:f00f:cafe::1"), net.ParseIP("2001:db8:f00f:cafe::1"), 100)) NewRandomAddressPool(net.ParseIP("2001:db8:f00f:cafe::1"), net.ParseIP("2001:db8:f00f:cafe::1"), 100))
msg := builder.MakeMsgInformationRequestReply(transactionId, expectedClientId, 0x11) msg := builder.MakeMsgInformationRequestReply(transactionId, expectedClientId, 0x11, expectedBootFileUrl)
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)
@ -200,18 +211,21 @@ func TestMakeMsgInformationRequestReply(t *testing.T) {
if bootfileUrlOption == nil { if bootfileUrlOption == nil {
t.Fatalf("Bootfile URL option should be present") t.Fatalf("Bootfile URL option should be present")
} }
if string(expectedBootFileUrl) != string(bootfileUrlOption.Value) {
t.Fatalf("Expected bootfile URL %v, got %v", expectedBootFileUrl, bootfileUrlOption)
}
} }
func TestMakeMsgInformationRequestReplyWithHttpClientArch(t *testing.T) { func TestMakeMsgInformationRequestReplyWithHttpClientArch(t *testing.T) {
expectedClientId := []byte("clientid") expectedClientId := []byte("clientid")
expectedServerId := []byte("serverid") expectedServerId := []byte("serverid")
transactionId := [3]byte{'1', '2', '3'} transactionId := [3]byte{'1', '2', '3'}
expectedBootFileUrl := []byte("http://bootfileurl")
bootConfig := MakeStaticBootConfiguration("httpbootfileurl", "ipxebootfileurl") builder := MakePacketBuilder(expectedServerId, 90, 100, nil,
builder := MakePacketBuilder(expectedServerId, 90, 100, bootConfig,
NewRandomAddressPool(net.ParseIP("2001:db8:f00f:cafe::1"), net.ParseIP("2001:db8:f00f:cafe::1"), 100)) NewRandomAddressPool(net.ParseIP("2001:db8:f00f:cafe::1"), net.ParseIP("2001:db8:f00f:cafe::1"), 100))
msg := builder.MakeMsgInformationRequestReply(transactionId, expectedClientId, 0x10) msg := builder.MakeMsgInformationRequestReply(transactionId, expectedClientId, 0x10, expectedBootFileUrl)
vendorClassOption := msg.Options[OptVendorClass] vendorClassOption := msg.Options[OptVendorClass]
if vendorClassOption == nil { if vendorClassOption == nil {
@ -222,6 +236,9 @@ func TestMakeMsgInformationRequestReplyWithHttpClientArch(t *testing.T) {
if bootfileUrlOption == nil { if bootfileUrlOption == nil {
t.Fatalf("Bootfile URL option should be present") t.Fatalf("Bootfile URL option should be present")
} }
if string(expectedBootFileUrl) != string(bootfileUrlOption.Value) {
t.Fatalf("Expected bootfile URL %v, got %v", expectedBootFileUrl, bootfileUrlOption)
}
} }
func TestMakeMsgReleaseReply(t *testing.T) { func TestMakeMsgReleaseReply(t *testing.T) {
@ -229,8 +246,7 @@ func TestMakeMsgReleaseReply(t *testing.T) {
expectedServerId := []byte("serverid") expectedServerId := []byte("serverid")
transactionId := [3]byte{'1', '2', '3'} transactionId := [3]byte{'1', '2', '3'}
bootConfig := MakeStaticBootConfiguration("httpbootfileurl", "ipxebootfileurl") builder := MakePacketBuilder(expectedServerId, 90, 100, nil,
builder := MakePacketBuilder(expectedServerId, 90, 100, bootConfig,
NewRandomAddressPool(net.ParseIP("2001:db8:f00f:cafe::1"), net.ParseIP("2001:db8:f00f:cafe::1"), 100)) NewRandomAddressPool(net.ParseIP("2001:db8:f00f:cafe::1"), net.ParseIP("2001:db8:f00f:cafe::1"), 100))
msg := builder.MakeMsgReleaseReply(transactionId, expectedClientId) msg := builder.MakeMsgReleaseReply(transactionId, expectedClientId)

View File

@ -4,6 +4,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"fmt" "fmt"
"go.universe.tf/netboot/pixiecorev6" "go.universe.tf/netboot/pixiecorev6"
"go.universe.tf/netboot/dhcp6"
) )
var bootIPv6Cmd = &cobra.Command{ var bootIPv6Cmd = &cobra.Command{
@ -37,8 +38,7 @@ var bootIPv6Cmd = &cobra.Command{
} }
s.Address = addr s.Address = addr
s.IPxeUrl = ipxeUrl s.BootUrls = dhcp6.MakeStaticBootConfiguration(httpBootUrl, ipxeUrl)
s.HttpbootUrl = httpBootUrl
fmt.Println(s.Serve()) fmt.Println(s.Serve())
}, },

View File

@ -0,0 +1,55 @@
package cli
import (
"github.com/spf13/cobra"
"fmt"
"go.universe.tf/netboot/pixiecorev6"
"go.universe.tf/netboot/dhcp6"
"time"
)
var ipv6ApiCmd = &cobra.Command{
Use: "ipv6api",
Short: "Boot a kernel and optional init ramdisks over IPv6 using api",
Run: func(cmd *cobra.Command, args []string) {
addr, err := cmd.Flags().GetString("listen-addr")
if err != nil {
fatalf("Error reading flag: %s", err)
}
apiUrl, err := cmd.Flags().GetString("api-request-url")
if err != nil {
fatalf("Error reading flag: %s", err)
}
apiTimeout, err := cmd.Flags().GetDuration("api-request-timeout")
if err != nil {
fatalf("Error reading flag: %s", err)
}
s := pixiecorev6.NewServerV6()
if addr == "" {
fatalf("Please specify address to listen on")
} else {
}
if apiUrl == "" {
fatalf("Please specify ipxe config file url")
}
s.Address = addr
s.BootUrls = dhcp6.MakeApiBootConfiguration(apiUrl, apiTimeout)
fmt.Println(s.Serve())
},
}
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")
}
func init() {
rootCmd.AddCommand(ipv6ApiCmd)
serverv6ApiConfigFlags(ipv6ApiCmd)
ipv6ApiCmd.Flags().Duration("api-request-timeout", 5*time.Second, "Timeout for request to the API server")
}

View File

@ -19,7 +19,15 @@ func (s *ServerV6) serveDHCP(conn *dhcp6.Conn, packetBuilder *dhcp6.PacketBuilde
s.log("dhcpv6", fmt.Sprintf("Received (%d) packet (%d): %s\n", pkt.Type, pkt.TransactionID, pkt.Options.HumanReadable())) s.log("dhcpv6", fmt.Sprintf("Received (%d) packet (%d): %s\n", pkt.Type, pkt.TransactionID, pkt.Options.HumanReadable()))
response := packetBuilder.BuildResponse(pkt) response, err := packetBuilder.BuildResponse(pkt)
if err != nil {
s.log("dhcpv6", fmt.Sprintf("Error creating response for transaction: %s: %s", pkt.TransactionID, err))
continue
}
if response == nil {
s.log("dhcpv6", fmt.Sprintf("Don't know how to respond to packet type: %d (transaction id %s)", pkt.Type, pkt.TransactionID))
continue
}
marshalled_response, err := response.Marshal() marshalled_response, err := response.Marshal()
if err != nil { if err != nil {

View File

@ -10,11 +10,10 @@ import (
) )
type ServerV6 struct { type ServerV6 struct {
Address string Address string
Port string Port string
Duid []byte Duid []byte
IPxeUrl string BootUrls dhcp6.BootConfiguration
HttpbootUrl string
errs chan error errs chan error
@ -56,8 +55,8 @@ func (s *ServerV6) Serve() error {
addressPool := dhcp6.NewRandomAddressPool(net.ParseIP("2001:db8:f00f:cafe::10"), net.ParseIP("2001:db8:f00f:cafe::100"), 1850) addressPool := dhcp6.NewRandomAddressPool(net.ParseIP("2001:db8:f00f:cafe::10"), net.ParseIP("2001:db8:f00f:cafe::100"), 1850)
// bootConfiguration := dhcp6.MakeStaticBootConfiguration("http://[2001:db8:f00f:cafe::4]/bootx64.efi", "http://[2001:db8:f00f:cafe::4]/script.ipxe") // 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) // bootConfiguration := dhcp6.MakeApiBootConfiguration("http://[2001:db8:f00f:cafe::4]:8888/", 10 *time.Second)
packetBuilder := dhcp6.MakePacketBuilder(s.Duid, 1800, 1850, bootConfiguration, addressPool) packetBuilder := dhcp6.MakePacketBuilder(s.Duid, 1800, 1850, s.BootUrls, addressPool)
go func() { s.errs <- s.serveDHCP(dhcp, packetBuilder) }() go func() { s.errs <- s.serveDHCP(dhcp, packetBuilder) }()