github.com/hugelgupf/u-root@v0.0.0-20191023214958-4807c632154c/pkg/ibft/ibft_test.go (about)

     1  // Copyright 2019 the u-root Authors. All rights reserved
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package ibft
     6  
     7  import (
     8  	"bytes"
     9  	"encoding/binary"
    10  	"encoding/hex"
    11  	"net"
    12  	"testing"
    13  
    14  	"github.com/davecgh/go-spew/spew"
    15  	"github.com/google/go-cmp/cmp"
    16  )
    17  
    18  var spewConfig = &spew.ConfigState{
    19  	Indent:                  "  ",
    20  	DisablePointerAddresses: true,
    21  	DisableCapacities:       true,
    22  }
    23  
    24  // Header is described in iBFT Spec 1.4.3.
    25  func emptyHeader() []byte {
    26  	return append([]byte("iBFT\x00\x00\x00\x00\x01\x00GoogleGoogIBFT"), bytes.Repeat([]byte{0}, 24)...)
    27  }
    28  
    29  func defaultControl() []byte {
    30  	return []byte{
    31  		0x01 /* Control ID */, 0x01 /* version */, 18, 0 /* length */, 0 /* index */, 0 /* flags */, 0, 0, /* extensions */
    32  		0x48, 0 /* Initiator */, 0x98, 0x0 /* NIC0 */, 0x0, 0x01 /* Target0 */, 0x0, 0x0 /* NIC1 */, 0x0, 0x0, /* Target1 */
    33  		0, 0, 0, 0, 0, 0, /* padding */
    34  	}
    35  }
    36  
    37  // Offsets are from iBFT Spec Section 1.4.5.
    38  func initiator(flags byte, nameLen uint16, nameOffset uint16) []byte {
    39  	b := append(append(
    40  		[]byte{0x02 /* Initiator ID */, 0x01 /* version */, 74, 0 /* length */, 0 /* index */, flags /* flags */},
    41  		bytes.Repeat([]byte{0}, 16*4)...),
    42  		0, 0 /* initiator name length */, 0, 0, /* initiator name offset */
    43  		0, 0, 0, 0, 0, 0, /* padding */
    44  	)
    45  	binary.LittleEndian.PutUint16(b[70:], nameLen)
    46  	binary.LittleEndian.PutUint16(b[72:], nameOffset)
    47  	return b
    48  }
    49  
    50  func emptyNIC() []byte {
    51  	return nic(0, nil, 0, nil, nil, nil, nil, 0)
    52  }
    53  
    54  // Offsets are from iBFT Spec Section 1.4.6.
    55  func nic(flags uint8, ip net.IP, subnetMaskPrefix uint8, gateway, dns, dhcp net.IP, mac net.HardwareAddr, bdf uint16) []byte {
    56  	empty := append(
    57  		append(
    58  			[]byte{0x03 /* NIC ID */, 0x01 /* version */, 102, 0 /* length */, 0 /* index */, flags /* flags */},
    59  			bytes.Repeat([]byte{0}, 16+1+1+16*4+2+6+2+2+2)..., /* all fields */
    60  		),
    61  		0, 0, /* padding for alignment */
    62  	)
    63  	if ip != nil {
    64  		copy(empty[6:], ip.To16())
    65  	}
    66  	empty[22] = subnetMaskPrefix
    67  	if gateway != nil {
    68  		copy(empty[24:], gateway.To16())
    69  	}
    70  	if dns != nil {
    71  		copy(empty[40:], dns.To16())
    72  	}
    73  	if dhcp != nil {
    74  		copy(empty[72:], dhcp.To16())
    75  	}
    76  	if mac != nil {
    77  		copy(empty[90:], mac)
    78  	}
    79  	binary.LittleEndian.PutUint16(empty[96:], bdf)
    80  	return empty
    81  }
    82  
    83  func emptyTarget() []byte {
    84  	return target(0, nil, 0, 0, 0)
    85  }
    86  
    87  // Offsets are from iBFT Spec Section 1.4.7.
    88  func target(flags uint8, ip net.IP, port uint16, nameLen uint16, nameOffset uint16) []byte {
    89  	empty := append(
    90  		[]byte{0x04 /* Target ID */, 0x01 /* version */, 54, 0 /* length */, 0 /* index */, flags /* flags */},
    91  		bytes.Repeat([]byte{0}, 49+1)..., /* all fields + 1 bytes padding for alignment */
    92  	)
    93  	if ip != nil {
    94  		copy(empty[6:], ip.To16())
    95  	}
    96  	binary.LittleEndian.PutUint16(empty[22:], port)
    97  	binary.LittleEndian.PutUint16(empty[34:], nameLen)
    98  	binary.LittleEndian.PutUint16(empty[36:], nameOffset)
    99  	return empty
   100  }
   101  
   102  func heap(s []string) []byte {
   103  	var h []byte
   104  	for _, t := range s {
   105  		h = append(h, []byte(t)...)
   106  		h = append(h, 0)
   107  	}
   108  	return h
   109  }
   110  
   111  func join(b ...[]byte) []byte {
   112  	var r []byte
   113  	for _, bb := range b {
   114  		r = append(r, bb...)
   115  	}
   116  	return r
   117  }
   118  
   119  func TestMarshal(t *testing.T) {
   120  	for _, tt := range []struct {
   121  		desc string
   122  		i    *IBFT
   123  		want []byte
   124  	}{
   125  		{
   126  			desc: "empty iBFT",
   127  			i:    &IBFT{},
   128  			want: fixACPIHeader(join(emptyHeader(), defaultControl(), initiator(0, 0, 0), emptyNIC(), emptyTarget())),
   129  		},
   130  		{
   131  			desc: "IBFT with relevant stuff.",
   132  			i: &IBFT{
   133  				Initiator: Initiator{
   134  					Valid: true,
   135  					Boot:  true,
   136  					Name:  "NERF",
   137  				},
   138  				NIC0: NIC{
   139  					Valid:  true,
   140  					Boot:   true,
   141  					Global: true,
   142  					IPNet: &net.IPNet{
   143  						IP:   net.IP{192, 168, 1, 15},
   144  						Mask: net.IPv4Mask(255, 255, 255, 0),
   145  					},
   146  					Gateway:    net.IP{192, 168, 1, 1},
   147  					PrimaryDNS: net.IP{8, 8, 8, 8},
   148  					DHCPServer: net.IP{192, 168, 1, 1},
   149  					MACAddress: net.HardwareAddr{52, 54, 00, 12, 34, 56},
   150  				},
   151  				Target0: Target{
   152  					Valid: true,
   153  					Boot:  true,
   154  					Target: &net.TCPAddr{
   155  						IP:   net.IP{192, 168, 1, 1},
   156  						Port: 3260,
   157  					},
   158  					TargetName: "iqn.2016-01.com.example:foo",
   159  				},
   160  			},
   161  			want: fixACPIHeader(join(
   162  				emptyHeader(),
   163  				defaultControl(),
   164  				initiator(1<<1|1, 4 /* len */, 0x138),
   165  				nic(1<<2|1<<1|1, net.IP{192, 168, 1, 15} /* ip */, 24 /* netmask */, net.IP{192, 168, 1, 1} /* gateway */, net.IP{8, 8, 8, 8} /* dns */, net.IP{192, 168, 1, 1} /* dhcp serv */, net.HardwareAddr{52, 54, 00, 12, 34, 56} /* mac */, 0 /* BDF */),
   166  				target(1<<1|1, net.IP{192, 168, 1, 1}, 3260, 27, 0x138+5),
   167  				heap([]string{"NERF", "iqn.2016-01.com.example:foo"})),
   168  			),
   169  		},
   170  	} {
   171  		t.Run(tt.desc, func(t *testing.T) {
   172  			got := tt.i.Marshal()
   173  
   174  			t.Logf("got:\n%s", hex.Dump(got))
   175  			t.Logf("want:\n%s", hex.Dump(tt.want))
   176  
   177  			if !cmp.Equal(got, tt.want) {
   178  				t.Errorf("IBFT(%s).Marshal() differences: %s", spewConfig.Sdump(tt.i), cmp.Diff(got, tt.want))
   179  			}
   180  		})
   181  	}
   182  }