mirror of
https://github.com/danderson/netboot.git
synced 2025-08-10 00:27:12 +02:00
added packet-generation tests
This commit is contained in:
parent
c39e902fd4
commit
f3faa8e10a
@ -81,7 +81,7 @@ func InterfaceIndexByAddress(ifAddr string) (*net.Interface, error) {
|
||||
func (c *Conn) RecvDHCP() (*Packet, net.IP, error) {
|
||||
b := make([]byte, 1500)
|
||||
for {
|
||||
packetSize, rcm, _, err := c.conn.ReadFrom(b)
|
||||
_, rcm, _, err := c.conn.ReadFrom(b)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@ -91,7 +91,10 @@ func (c *Conn) RecvDHCP() (*Packet, net.IP, error) {
|
||||
if !rcm.Dst.IsMulticast() || !rcm.Dst.Equal(c.group) {
|
||||
continue // unknown group, discard
|
||||
}
|
||||
pkt := MakePacket(b, packetSize)
|
||||
pkt, err := MakePacket(b)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return pkt, rcm.Src, nil
|
||||
}
|
||||
|
@ -131,9 +131,13 @@ func (o *Option) Marshal() ([]byte, error) {
|
||||
}
|
||||
|
||||
func (o Options) UnmarshalOptionRequestOption() map[uint16]bool {
|
||||
oro_content := o[OptOro].Value
|
||||
to_ret := make(map[uint16]bool)
|
||||
|
||||
if o[OptOro] == nil {
|
||||
return to_ret
|
||||
}
|
||||
|
||||
oro_content := o[OptOro].Value
|
||||
for i := 0; i < int(o[OptOro].Length)/2; i++ {
|
||||
to_ret[uint16(binary.BigEndian.Uint16(oro_content[i*2:(i+1)*2]))] = true
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"net"
|
||||
"encoding/binary"
|
||||
"bytes"
|
||||
"golang.org/x/tools/go/gcimporter15/testdata"
|
||||
)
|
||||
|
||||
type MessageType uint8
|
||||
@ -32,7 +31,7 @@ type Packet struct {
|
||||
Options Options
|
||||
}
|
||||
|
||||
func MakePacket(bs []byte, len int) (*Packet, error) {
|
||||
func MakePacket(bs []byte) (*Packet, error) {
|
||||
options, err := MakeOptions(bs[4:]) // 4:len?
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("packet has malformed options section: %s", err)
|
||||
@ -58,9 +57,9 @@ func (p *Packet) Marshal() ([]byte, error) {
|
||||
|
||||
func (p *Packet) BuildResponse(serverDuid []byte) *Packet {
|
||||
transactionId := p.TransactionID
|
||||
clientId := in_options[OptClientId].Value
|
||||
iaNaId := in_options[OptIaNa].Value[0:4]
|
||||
clientArchType := in_options[OptClientArchType].Value
|
||||
clientId := p.Options[OptClientId].Value
|
||||
iaNaId := p.Options[OptIaNa].Value[0:4]
|
||||
clientArchType := p.Options[OptClientArchType].Value
|
||||
|
||||
switch p.Type {
|
||||
case MsgSolicit:
|
||||
|
329
dhcp6/packet_test.go
Normal file
329
dhcp6/packet_test.go
Normal file
@ -0,0 +1,329 @@
|
||||
package dhcp6
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"encoding/binary"
|
||||
)
|
||||
|
||||
func TestMakeMsgAdvertise(t *testing.T) {
|
||||
expectedClientId := []byte("clientid")
|
||||
expectedServerId := []byte("serverid")
|
||||
transactionId := [3]byte{'1', '2', '3'}
|
||||
|
||||
msg := MakeMsgAdvertise(transactionId, expectedServerId, expectedClientId, []byte("1234"), []byte("11"))
|
||||
|
||||
if msg.Type != MsgAdvertise {
|
||||
t.Fatalf("Expected message type %d, got %d", MsgAdvertise, msg.Type)
|
||||
}
|
||||
if transactionId != msg.TransactionID {
|
||||
t.Fatalf("Expected transaction Id %v, got %v", transactionId, msg.TransactionID)
|
||||
}
|
||||
|
||||
clientIdOption := msg.Options[OptClientId]
|
||||
if clientIdOption == nil {
|
||||
t.Fatalf("Client Id option should be present")
|
||||
}
|
||||
if string(expectedClientId) != string(clientIdOption.Value) {
|
||||
t.Fatalf("Expected client id %v, got %v", expectedClientId, clientIdOption.Value)
|
||||
}
|
||||
if len(expectedClientId) != len(clientIdOption.Value) {
|
||||
t.Fatalf("Expected client id length of %d, got %d", len(expectedClientId), len(clientIdOption.Value))
|
||||
}
|
||||
|
||||
serverIdOption := msg.Options[OptServerId]
|
||||
if serverIdOption == nil {
|
||||
t.Fatalf("Server Id option should be present")
|
||||
}
|
||||
if string(expectedServerId) != string(serverIdOption.Value) {
|
||||
t.Fatalf("Expected server id %v, got %v", expectedClientId, serverIdOption.Value)
|
||||
}
|
||||
if len(expectedServerId) != len(serverIdOption.Value) {
|
||||
t.Fatalf("Expected server id length of %d, got %d", len(expectedClientId), len(serverIdOption.Value))
|
||||
}
|
||||
|
||||
bootfileUrlOption := msg.Options[OptBootfileUrl]
|
||||
if bootfileUrlOption == nil {
|
||||
t.Fatalf("Bootfile URL option should be present")
|
||||
}
|
||||
|
||||
iaNaOption := msg.Options[OptIaNa]
|
||||
if iaNaOption == nil {
|
||||
t.Fatalf("interface non-temporary association option should be present")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMakeMsgAdvertiseWithHttpClientArch(t *testing.T) {
|
||||
expectedClientId := []byte("clientid")
|
||||
expectedServerId := []byte("serverid")
|
||||
transactionId := [3]byte{'1', '2', '3'}
|
||||
|
||||
msg := MakeMsgAdvertise(transactionId, expectedServerId, expectedClientId, []byte("1234"), []byte{0x0, 0x10})
|
||||
|
||||
vendorClassOption := msg.Options[OptVendorClass]
|
||||
if vendorClassOption == nil {
|
||||
t.Fatalf("Vendor class option should be present")
|
||||
}
|
||||
|
||||
bootfileUrlOption := msg.Options[OptBootfileUrl]
|
||||
if bootfileUrlOption == nil {
|
||||
t.Fatalf("Bootfile URL option should be present")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMakeMsgReply(t *testing.T) {
|
||||
expectedClientId := []byte("clientid")
|
||||
expectedServerId := []byte("serverid")
|
||||
transactionId := [3]byte{'1', '2', '3'}
|
||||
|
||||
msg := MakeMsgReply(transactionId, expectedServerId, expectedClientId, []byte("1234"), []byte("11"))
|
||||
|
||||
if msg.Type != MsgReply {
|
||||
t.Fatalf("Expected message type %d, got %d", MsgAdvertise, msg.Type)
|
||||
}
|
||||
if transactionId != msg.TransactionID {
|
||||
t.Fatalf("Expected transaction Id %v, got %v", transactionId, msg.TransactionID)
|
||||
}
|
||||
|
||||
clientIdOption := msg.Options[OptClientId]
|
||||
if clientIdOption == nil {
|
||||
t.Fatalf("Client Id option should be present")
|
||||
}
|
||||
if string(expectedClientId) != string(clientIdOption.Value) {
|
||||
t.Fatalf("Expected client id %v, got %v", expectedClientId, clientIdOption.Value)
|
||||
}
|
||||
if len(expectedClientId) != len(clientIdOption.Value) {
|
||||
t.Fatalf("Expected client id length of %d, got %d", len(expectedClientId), len(clientIdOption.Value))
|
||||
}
|
||||
|
||||
serverIdOption := msg.Options[OptServerId]
|
||||
if serverIdOption == nil {
|
||||
t.Fatalf("Server Id option should be present")
|
||||
}
|
||||
if string(expectedServerId) != string(serverIdOption.Value) {
|
||||
t.Fatalf("Expected server id %v, got %v", expectedClientId, serverIdOption.Value)
|
||||
}
|
||||
if len(expectedServerId) != len(serverIdOption.Value) {
|
||||
t.Fatalf("Expected server id length of %d, got %d", len(expectedClientId), len(serverIdOption.Value))
|
||||
}
|
||||
|
||||
bootfileUrlOption := msg.Options[OptBootfileUrl]
|
||||
if bootfileUrlOption == nil {
|
||||
t.Fatalf("Bootfile URL option should be present")
|
||||
}
|
||||
|
||||
iaNaOption := msg.Options[OptIaNa]
|
||||
if iaNaOption == nil {
|
||||
t.Fatalf("interface non-temporary association option should be present")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMakeMsgReplyWithHttpClientArch(t *testing.T) {
|
||||
expectedClientId := []byte("clientid")
|
||||
expectedServerId := []byte("serverid")
|
||||
transactionId := [3]byte{'1', '2', '3'}
|
||||
|
||||
msg := MakeMsgReply(transactionId, expectedServerId, expectedClientId, []byte("1234"), []byte{0x0, 0x10})
|
||||
|
||||
vendorClassOption := msg.Options[OptVendorClass]
|
||||
if vendorClassOption == nil {
|
||||
t.Fatalf("Vendor class option should be present")
|
||||
}
|
||||
|
||||
bootfileUrlOption := msg.Options[OptBootfileUrl]
|
||||
if bootfileUrlOption == nil {
|
||||
t.Fatalf("Bootfile URL option should be present")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMakeMsgInformationRequestReply(t *testing.T) {
|
||||
expectedClientId := []byte("clientid")
|
||||
expectedServerId := []byte("serverid")
|
||||
transactionId := [3]byte{'1', '2', '3'}
|
||||
|
||||
msg := MakeMsgInformationRequestReply(transactionId, expectedServerId, expectedClientId, []byte("11"))
|
||||
|
||||
|
||||
if msg.Type != MsgReply {
|
||||
t.Fatalf("Expected message type %d, got %d", MsgAdvertise, msg.Type)
|
||||
}
|
||||
if transactionId != msg.TransactionID {
|
||||
t.Fatalf("Expected transaction Id %v, got %v", transactionId, msg.TransactionID)
|
||||
}
|
||||
|
||||
clientIdOption := msg.Options[OptClientId]
|
||||
if clientIdOption == nil {
|
||||
t.Fatalf("Client Id option should be present")
|
||||
}
|
||||
if string(expectedClientId) != string(clientIdOption.Value) {
|
||||
t.Fatalf("Expected client id %v, got %v", expectedClientId, clientIdOption.Value)
|
||||
}
|
||||
if len(expectedClientId) != len(clientIdOption.Value) {
|
||||
t.Fatalf("Expected client id length of %d, got %d", len(expectedClientId), len(clientIdOption.Value))
|
||||
}
|
||||
|
||||
serverIdOption := msg.Options[OptServerId]
|
||||
if serverIdOption == nil {
|
||||
t.Fatalf("Server Id option should be present")
|
||||
}
|
||||
if string(expectedServerId) != string(serverIdOption.Value) {
|
||||
t.Fatalf("Expected server id %v, got %v", expectedClientId, serverIdOption.Value)
|
||||
}
|
||||
if len(expectedServerId) != len(serverIdOption.Value) {
|
||||
t.Fatalf("Expected server id length of %d, got %d", len(expectedClientId), len(serverIdOption.Value))
|
||||
}
|
||||
|
||||
bootfileUrlOption := msg.Options[OptBootfileUrl]
|
||||
if bootfileUrlOption == nil {
|
||||
t.Fatalf("Bootfile URL option should be present")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMakeMsgInformationRequestReplyWithHttpClientArch(t *testing.T) {
|
||||
expectedClientId := []byte("clientid")
|
||||
expectedServerId := []byte("serverid")
|
||||
transactionId := [3]byte{'1', '2', '3'}
|
||||
|
||||
msg := MakeMsgInformationRequestReply(transactionId, expectedServerId, expectedClientId, []byte{0x0, 0x10})
|
||||
|
||||
vendorClassOption := msg.Options[OptVendorClass]
|
||||
if vendorClassOption == nil {
|
||||
t.Fatalf("Vendor class option should be present")
|
||||
}
|
||||
|
||||
bootfileUrlOption := msg.Options[OptBootfileUrl]
|
||||
if bootfileUrlOption == nil {
|
||||
t.Fatalf("Bootfile URL option should be present")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMakeMsgReleaseReply(t *testing.T) {
|
||||
expectedClientId := []byte("clientid")
|
||||
expectedServerId := []byte("serverid")
|
||||
transactionId := [3]byte{'1', '2', '3'}
|
||||
|
||||
msg := MakeMsgReleaseReply(transactionId, expectedServerId, expectedClientId)
|
||||
|
||||
if msg.Type != MsgReply {
|
||||
t.Fatalf("Expected message type %d, got %d", MsgAdvertise, msg.Type)
|
||||
}
|
||||
if transactionId != msg.TransactionID {
|
||||
t.Fatalf("Expected transaction Id %v, got %v", transactionId, msg.TransactionID)
|
||||
}
|
||||
|
||||
clientIdOption := msg.Options[OptClientId]
|
||||
if clientIdOption == nil {
|
||||
t.Fatalf("Client Id option should be present")
|
||||
}
|
||||
if string(expectedClientId) != string(clientIdOption.Value) {
|
||||
t.Fatalf("Expected client id %v, got %v", expectedClientId, clientIdOption.Value)
|
||||
}
|
||||
if len(expectedClientId) != len(clientIdOption.Value) {
|
||||
t.Fatalf("Expected client id length of %d, got %d", len(expectedClientId), len(clientIdOption.Value))
|
||||
}
|
||||
|
||||
serverIdOption := msg.Options[OptServerId]
|
||||
if serverIdOption == nil {
|
||||
t.Fatalf("Server Id option should be present")
|
||||
}
|
||||
if string(expectedServerId) != string(serverIdOption.Value) {
|
||||
t.Fatalf("Expected server id %v, got %v", expectedClientId, serverIdOption.Value)
|
||||
}
|
||||
if len(expectedServerId) != len(serverIdOption.Value) {
|
||||
t.Fatalf("Expected server id length of %d, got %d", len(expectedClientId), len(serverIdOption.Value))
|
||||
}
|
||||
}
|
||||
|
||||
func TestShouldDiscardSolicitWithoutBootfileUrlOption(t *testing.T) {
|
||||
clientId := []byte("clientid")
|
||||
options := make(Options)
|
||||
options.AddOption(&Option{Id: OptClientId, Length: uint16(len(clientId)), Value: clientId})
|
||||
solicit := &Packet{Type: MsgSolicit, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
||||
|
||||
if err := ShouldDiscardSolicit(solicit); err == nil {
|
||||
t.Fatalf("Should discard solicit packet without bootfile url option, but didn't")
|
||||
}
|
||||
}
|
||||
|
||||
func TestShouldDiscardSolicitWithoutClientIdOption(t *testing.T) {
|
||||
options := make(Options)
|
||||
options.AddOption(MakeOptionRequestOptions([]uint16{OptBootfileUrl}))
|
||||
solicit := &Packet{Type: MsgSolicit, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
||||
|
||||
if err := ShouldDiscardSolicit(solicit); err == nil {
|
||||
t.Fatalf("Should discard solicit packet without client id option, but didn't")
|
||||
}
|
||||
}
|
||||
|
||||
func TestShouldDiscardSolicitWithServerIdOption(t *testing.T) {
|
||||
serverId := []byte("serverid")
|
||||
clientId := []byte("clientid")
|
||||
options := make(Options)
|
||||
options.AddOption(MakeOptionRequestOptions([]uint16{OptBootfileUrl}))
|
||||
options.AddOption(&Option{Id: OptClientId, Length: uint16(len(clientId)), Value: clientId})
|
||||
options.AddOption(&Option{Id: OptServerId, Length: uint16(len(serverId)), Value: serverId})
|
||||
solicit := &Packet{Type: MsgSolicit, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
||||
|
||||
if err := ShouldDiscardSolicit(solicit); err == nil {
|
||||
t.Fatalf("Should discard solicit packet with server id option, but didn't")
|
||||
}
|
||||
}
|
||||
|
||||
func TestShouldDiscardRequestWithoutBootfileUrlOption(t *testing.T) {
|
||||
serverId := []byte("serverid")
|
||||
clientId := []byte("clientid")
|
||||
options := make(Options)
|
||||
options.AddOption(&Option{Id: OptClientId, Length: uint16(len(clientId)), Value: clientId})
|
||||
options.AddOption(&Option{Id: OptServerId, Length: uint16(len(serverId)), Value: serverId})
|
||||
request := &Packet{Type: MsgRequest, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
||||
|
||||
if err := ShouldDiscardRequest(request, serverId); err == nil {
|
||||
t.Fatalf("Should discard request packet without bootfile url option, but didn't")
|
||||
}
|
||||
}
|
||||
|
||||
func TestShouldDiscardRequestWithoutClientIdOption(t *testing.T) {
|
||||
serverId := []byte("serverid")
|
||||
options := make(Options)
|
||||
options.AddOption(MakeOptionRequestOptions([]uint16{OptBootfileUrl}))
|
||||
options.AddOption(&Option{Id: OptServerId, Length: uint16(len(serverId)), Value: serverId})
|
||||
request := &Packet{Type: MsgRequest, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
||||
|
||||
if err := ShouldDiscardRequest(request, serverId); err == nil {
|
||||
t.Fatalf("Should discard request packet without client id option, but didn't")
|
||||
}
|
||||
}
|
||||
|
||||
func TestShouldDiscardRequestWithoutServerIdOption(t *testing.T) {
|
||||
clientId := []byte("clientid")
|
||||
options := make(Options)
|
||||
options.AddOption(MakeOptionRequestOptions([]uint16{OptBootfileUrl}))
|
||||
options.AddOption(&Option{Id: OptClientId, Length: uint16(len(clientId)), Value: clientId})
|
||||
request := &Packet{Type: MsgRequest, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
||||
|
||||
if err := ShouldDiscardRequest(request, []byte("serverid")); err == nil {
|
||||
t.Fatalf("Should discard request packet with server id option, but didn't")
|
||||
}
|
||||
}
|
||||
|
||||
func TestShouldDiscardRequestWithWrongServerId(t *testing.T) {
|
||||
clientId := []byte("clientid")
|
||||
serverId := []byte("serverid")
|
||||
options := make(Options)
|
||||
options.AddOption(MakeOptionRequestOptions([]uint16{OptBootfileUrl}))
|
||||
options.AddOption(&Option{Id: OptClientId, Length: uint16(len(clientId)), Value: clientId})
|
||||
options.AddOption(&Option{Id: OptServerId, Length: uint16(len(serverId)), Value: serverId})
|
||||
request := &Packet{Type: MsgRequest, TransactionID: [3]byte{'1', '2', '3'}, Options: options}
|
||||
|
||||
if err := ShouldDiscardRequest(request, []byte("wrongid")); err == nil {
|
||||
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) {
|
||||
binary.BigEndian.PutUint16(value[i*2:], option)
|
||||
}
|
||||
|
||||
return &Option{Id: OptOro, Length: uint16(len(options)*2), Value: value}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user