New Upstream Release - golang-github-d2g-dhcp4
Ready changes
Summary
Merged new upstream version: 0.0~git20170904.a1d1b6c (was: 0.0~git20150413).
Resulting package
Built on 2022-12-14T03:56 (took 10m24s)
The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:
apt install -t fresh-releases golang-github-d2g-dhcp4-dev
Lintian Result
Diff
diff --git a/debian/changelog b/debian/changelog
index c5a3bbd..551c35d 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+golang-github-d2g-dhcp4 (0.0~git20170904.a1d1b6c-1) UNRELEASED; urgency=low
+
+ * New upstream snapshot.
+
+ -- Debian Janitor <janitor@jelmer.uk> Wed, 14 Dec 2022 03:46:58 -0000
+
golang-github-d2g-dhcp4 (0.0~git20150413-4) unstable; urgency=medium
[ Debian Janitor ]
diff --git a/helpers_test.go b/helpers_test.go
new file mode 100644
index 0000000..6b364e8
--- /dev/null
+++ b/helpers_test.go
@@ -0,0 +1,397 @@
+package dhcp4
+
+import (
+ "bytes"
+ "net"
+ "reflect"
+ "sort"
+ "testing"
+ "time"
+)
+
+// Verify that all options are returned by Options.SelectOrderOrAll if
+// the input order value is nil.
+func TestSelectOrderOrAllNil(t *testing.T) {
+ assertOptionsSlices(t, 0, "nil order", allOptionsSlice, optMap.SelectOrderOrAll(nil))
+}
+
+// Verify that all options are returned by Options.SelectOrderOrAll if
+// the input order value is not nil over several tests.
+func TestSelectOrderOrAllNotNil(t *testing.T) {
+ for i, tt := range selectOrderTests {
+ assertOptionsSlices(t, i, tt.description, tt.result, optMap.SelectOrderOrAll(tt.order))
+ }
+}
+
+// Verify that no options are returned by Options.SelectOrder if
+// the input order value is nil.
+func TestSelectOrderNil(t *testing.T) {
+ assertOptionsSlices(t, 0, "nil order", nil, optMap.SelectOrder(nil))
+}
+
+// Verify that all options are returned by Options.SelectOrder if
+// the input order value is not nil over several tests.
+func TestSelectOrderNotNil(t *testing.T) {
+ for i, tt := range selectOrderTests {
+ assertOptionsSlices(t, i, tt.description, tt.result, optMap.SelectOrder(tt.order))
+ }
+}
+
+func TestIPRange(t *testing.T) {
+ var tests = []struct {
+ start net.IP
+ stop net.IP
+ result int
+ }{
+ {
+ start: net.IPv4(192, 168, 1, 1),
+ stop: net.IPv4(192, 168, 1, 1),
+ result: 1,
+ },
+ {
+ start: net.IPv4(192, 168, 1, 1),
+ stop: net.IPv4(192, 168, 1, 254),
+ result: 254,
+ },
+ {
+ start: net.IPv4(192, 168, 1, 1),
+ stop: net.IPv4(192, 168, 10, 1),
+ result: 2305,
+ },
+ {
+ start: net.IPv4(172, 16, 1, 1),
+ stop: net.IPv4(192, 168, 1, 1),
+ result: 345505793,
+ },
+ }
+
+ for _, tt := range tests {
+ if result := IPRange(tt.start, tt.stop); result != tt.result {
+ t.Fatalf("IPRange(%s, %s), unexpected result: %v != %v",
+ tt.start, tt.stop, result, tt.result)
+ }
+ }
+}
+
+func TestIPAdd(t *testing.T) {
+ var tests = []struct {
+ start net.IP
+ add int
+ result net.IP
+ }{
+ {
+ start: net.IPv4(192, 168, 1, 1),
+ add: 0,
+ result: net.IPv4(192, 168, 1, 1),
+ },
+ {
+ start: net.IPv4(192, 168, 1, 1),
+ add: 253,
+ result: net.IPv4(192, 168, 1, 254),
+ },
+ {
+ start: net.IPv4(192, 168, 1, 1),
+ add: 1024,
+ result: net.IPv4(192, 168, 5, 1),
+ },
+ {
+ start: net.IPv4(192, 168, 1, 1),
+ add: 4096,
+ result: net.IPv4(192, 168, 17, 1),
+ },
+ }
+
+ for _, tt := range tests {
+ if result := IPAdd(tt.start, tt.add); !result.Equal(tt.result) {
+ t.Fatalf("IPAdd(%s, %d), unexpected result: %v != %v",
+ tt.start, tt.add, result, tt.result)
+ }
+ }
+}
+
+func TestIPLess(t *testing.T) {
+ var tests = []struct {
+ a net.IP
+ b net.IP
+ result bool
+ }{
+ {
+ a: net.IPv4(192, 168, 1, 1),
+ b: net.IPv4(192, 168, 1, 1),
+ result: false,
+ },
+ {
+ a: net.IPv4(192, 168, 1, 1),
+ b: net.IPv4(192, 168, 0, 1),
+ result: false,
+ },
+ {
+ a: net.IPv4(192, 168, 0, 1),
+ b: net.IPv4(192, 168, 1, 1),
+ result: true,
+ },
+ {
+ a: net.IPv4(192, 168, 0, 1),
+ b: net.IPv4(192, 168, 10, 1),
+ result: true,
+ },
+ }
+
+ for _, tt := range tests {
+ if result := IPLess(tt.a, tt.b); result != tt.result {
+ t.Fatalf("IPLess(%s, %s), unexpected result: %v != %v",
+ tt.a, tt.b, result, tt.result)
+ }
+ }
+}
+
+func TestIPInRange(t *testing.T) {
+ var tests = []struct {
+ start net.IP
+ stop net.IP
+ ip net.IP
+ result bool
+ }{
+ {
+ start: net.IPv4(192, 168, 1, 1),
+ stop: net.IPv4(192, 168, 2, 1),
+ ip: net.IPv4(192, 168, 3, 1),
+ result: false,
+ },
+ {
+ start: net.IPv4(192, 168, 1, 1),
+ stop: net.IPv4(192, 168, 10, 1),
+ ip: net.IPv4(192, 168, 0, 1),
+ result: false,
+ },
+ {
+ start: net.IPv4(192, 168, 1, 1),
+ stop: net.IPv4(192, 168, 10, 1),
+ ip: net.IPv4(192, 168, 5, 1),
+ result: true,
+ },
+ {
+ start: net.IPv4(192, 168, 1, 1),
+ stop: net.IPv4(192, 168, 3, 1),
+ ip: net.IPv4(192, 168, 3, 0),
+ result: true,
+ },
+ {
+ start: net.IPv4(192, 168, 1, 1),
+ stop: net.IPv4(192, 168, 1, 1),
+ ip: net.IPv4(192, 168, 1, 1),
+ result: true,
+ },
+ }
+
+ for _, tt := range tests {
+ if result := IPInRange(tt.start, tt.stop, tt.ip); result != tt.result {
+ t.Fatalf("IPInRange(%s, %s, %s), unexpected result: %v != %v",
+ tt.start, tt.stop, tt.ip, result, tt.result)
+ }
+ }
+}
+
+func TestOptionsLeaseTime(t *testing.T) {
+ var tests = []struct {
+ duration time.Duration
+ result []byte
+ }{
+ {
+ duration: 0 * time.Second,
+ result: []byte{0, 0, 0, 0},
+ },
+ {
+ duration: 2 * time.Second,
+ result: []byte{0, 0, 0, 2},
+ },
+ {
+ duration: 60 * time.Second,
+ result: []byte{0, 0, 0, 60},
+ },
+ {
+ duration: 6 * time.Hour,
+ result: []byte{0, 0, 84, 96},
+ },
+ {
+ duration: 24 * time.Hour,
+ result: []byte{0, 1, 81, 128},
+ },
+ {
+ duration: 365 * 24 * time.Hour,
+ result: []byte{1, 225, 51, 128},
+ },
+ }
+
+ for _, tt := range tests {
+ if result := OptionsLeaseTime(tt.duration); !bytes.Equal(result, tt.result) {
+ t.Fatalf("OptionsLeaseTime(%s), unexpected result: %v != %v",
+ tt.duration, result, tt.result)
+ }
+ }
+}
+
+func TestJoinIPs(t *testing.T) {
+ var tests = []struct {
+ ips []net.IP
+ result []byte
+ }{
+ {
+ ips: []net.IP{net.IPv4(10, 0, 0, 1)},
+ result: []byte{10, 0, 0, 1},
+ },
+ {
+ ips: []net.IP{net.IPv4(192, 168, 1, 1), net.IPv4(192, 168, 2, 1)},
+ result: []byte{192, 168, 1, 1, 192, 168, 2, 1},
+ },
+ {
+ ips: []net.IP{net.IPv4(10, 0, 0, 1), net.IPv4(255, 255, 255, 254)},
+ result: []byte{10, 0, 0, 1, 255, 255, 255, 254},
+ },
+ {
+ ips: []net.IP{net.IPv4(8, 8, 8, 8), net.IPv4(8, 8, 4, 4), net.IPv4(192, 168, 1, 1)},
+ result: []byte{8, 8, 8, 8, 8, 8, 4, 4, 192, 168, 1, 1},
+ },
+ }
+
+ for _, tt := range tests {
+ if result := JoinIPs(tt.ips); !bytes.Equal(result, tt.result) {
+ t.Fatalf("JoinIPs(%s), unexpected result: %v != %v",
+ tt.ips, result, tt.result)
+ }
+ }
+}
+
+// byOptionCode implements sort.Interface for []Option.
+type byOptionCode []Option
+
+func (b byOptionCode) Len() int { return len(b) }
+func (b byOptionCode) Less(i int, j int) bool { return b[i].Code < b[j].Code }
+func (b byOptionCode) Swap(i int, j int) { b[i], b[j] = b[j], b[i] }
+
+// assertOptionsSlices is a test helper which verifies that two options slices
+// are identical. Several parameters are passed for easy identification of
+// failing tests.
+func assertOptionsSlices(t *testing.T, i int, description string, want []Option, got []Option) {
+ // Verify slices are same length
+ if want, got := len(want), len(got); want != got {
+ t.Fatalf("%02d: test %q, mismatched length: %d != %d",
+ i, description, want, got)
+ }
+
+ // Sort slices
+ sort.Sort(byOptionCode(want))
+ sort.Sort(byOptionCode(got))
+
+ // Verify slices are identical
+ if len(want) > 0 && len(got) > 0 && !reflect.DeepEqual(want, got) {
+ t.Fatalf("%02d: test %q, unexpected options: %v != %v",
+ i, description, want, got)
+ }
+}
+
+// optMap is an Options map which contains a number of option
+// codes and values, used for testing.
+var optMap = Options{
+ OptionSubnetMask: []byte{255, 255, 255, 0},
+ OptionRouter: []byte{192, 168, 1, 1},
+ OptionDomainNameServer: []byte{192, 168, 1, 2},
+ OptionTimeServer: []byte{192, 168, 1, 3},
+ OptionLogServer: []byte{192, 168, 1, 4},
+}
+
+// allOptionsSlice is a []Option derived from optMap. It is used
+// for some tests.
+var allOptionsSlice = []Option{
+ Option{
+ Code: OptionSubnetMask,
+ Value: optMap[OptionSubnetMask],
+ },
+ Option{
+ Code: OptionRouter,
+ Value: optMap[OptionRouter],
+ },
+ Option{
+ Code: OptionDomainNameServer,
+ Value: optMap[OptionDomainNameServer],
+ },
+ Option{
+ Code: OptionTimeServer,
+ Value: optMap[OptionTimeServer],
+ },
+ Option{
+ Code: OptionLogServer,
+ Value: optMap[OptionLogServer],
+ },
+}
+
+// selectOrderTests is a set of tests used for Options.SelectOrder
+// and Options.SelectOrderOrAll methods.
+var selectOrderTests = []struct {
+ description string
+ order []byte
+ result []Option
+}{
+ {
+ description: "subnet mask only",
+ order: []byte{
+ byte(OptionSubnetMask),
+ },
+ result: []Option{
+ Option{
+ Code: OptionSubnetMask,
+ Value: optMap[OptionSubnetMask],
+ },
+ },
+ },
+ {
+ description: "subnet mask and time server",
+ order: []byte{
+ byte(OptionSubnetMask),
+ byte(OptionTimeServer),
+ },
+ result: []Option{
+ Option{
+ Code: OptionSubnetMask,
+ Value: optMap[OptionSubnetMask],
+ },
+ Option{
+ Code: OptionTimeServer,
+ Value: optMap[OptionTimeServer],
+ },
+ },
+ },
+ {
+ description: "domain name server, time server, router",
+ order: []byte{
+ byte(OptionDomainNameServer),
+ byte(OptionTimeServer),
+ byte(OptionRouter),
+ },
+ result: []Option{
+ Option{
+ Code: OptionDomainNameServer,
+ Value: optMap[OptionDomainNameServer],
+ },
+ Option{
+ Code: OptionTimeServer,
+ Value: optMap[OptionTimeServer],
+ },
+ Option{
+ Code: OptionRouter,
+ Value: optMap[OptionRouter],
+ },
+ },
+ },
+ {
+ description: "all options in order",
+ order: []byte{
+ byte(OptionSubnetMask),
+ byte(OptionRouter),
+ byte(OptionDomainNameServer),
+ byte(OptionTimeServer),
+ byte(OptionLogServer),
+ },
+ result: allOptionsSlice,
+ },
+}
diff --git a/option.go b/option.go
index f3239e1..fbf86e6 100644
--- a/option.go
+++ b/option.go
@@ -11,7 +11,7 @@ type Option struct {
type Options map[OptionCode][]byte
// SelectOrderOrAll has same functionality as SelectOrder, except if the order
-// param is nil, whereby all options are added (in arbitary order).
+// param is nil, whereby all options are added (in arbitrary order).
func (o Options) SelectOrderOrAll(order []byte) []Option {
if order == nil {
opts := make([]Option, 0, len(o))
diff --git a/packet.go b/packet.go
index 5e547c8..25d69fb 100644
--- a/packet.go
+++ b/packet.go
@@ -127,10 +127,11 @@ func ReplyPacket(req Packet, mt MessageType, serverId, yIAddr net.IP, leaseDurat
p.SetYIAddr(yIAddr)
p.SetGIAddr(req.GIAddr())
p.SetCHAddr(req.CHAddr())
- p.SetSecs(req.Secs())
p.AddOption(OptionDHCPMessageType, []byte{byte(mt)})
p.AddOption(OptionServerIdentifier, []byte(serverId))
- p.AddOption(OptionIPAddressLeaseTime, OptionsLeaseTime(leaseDuration))
+ if leaseDuration > 0 {
+ p.AddOption(OptionIPAddressLeaseTime, OptionsLeaseTime(leaseDuration))
+ }
for _, o := range options {
p.AddOption(o.Code, o.Value)
}
diff --git a/packet_test.go b/packet_test.go
new file mode 100644
index 0000000..b0839cb
--- /dev/null
+++ b/packet_test.go
@@ -0,0 +1,433 @@
+package dhcp4
+
+import (
+ "bytes"
+ "net"
+ "testing"
+ "time"
+)
+
+func TestNewPacket(t *testing.T) {
+ var tests = []struct {
+ description string
+ opCode OpCode
+ }{
+ {
+ description: "boot request",
+ opCode: BootRequest,
+ },
+ {
+ description: "boot reply",
+ opCode: BootReply,
+ },
+ {
+ description: "unknown opcode",
+ opCode: 3,
+ },
+ }
+
+ for i, tt := range tests {
+ if want, got := newPacket(tt.opCode), NewPacket(tt.opCode); !bytes.Equal(want, got) {
+ t.Fatalf("%02d: NewPacket(%d), test %q, unexpected result: %v != %v",
+ i, tt.opCode, tt.description, want, got)
+ }
+ }
+}
+
+func TestPacketAddOption(t *testing.T) {
+ for i, tt := range optionsTests {
+ // Set up new packet, apply options from slice
+ p := NewPacket(BootRequest)
+ for _, o := range tt.options {
+ p.AddOption(o.Code, o.Value)
+ }
+
+ // Empty options should result in no changes
+ if tt.options == nil || len(tt.options) == 0 {
+ if !bytes.Equal(p, NewPacket(BootRequest)) {
+ t.Fatalf("%02d: test %q, no options applied, but packet contained extra data",
+ i, tt.description)
+ }
+ }
+
+ // Check that each option was properly applied, in order
+
+ // Track length of previous option bytes
+ var offset int
+ for ii, o := range tt.options {
+ // Options start at byte 240 on an empty packet, adding
+ // offset as loops continue
+ start := offset + 240
+ end := start + 2 + len(o.Value)
+
+ // Options bytes: [option] [length] [value...]
+ check := append([]byte{byte(o.Code)}, byte(len(o.Value)))
+ check = append(check, o.Value...)
+
+ // Verify option correctly applied
+ if want, got := p[start:end], check; !bytes.Equal(want, got) {
+ t.Fatalf("%02d: test %q, unexpected option bytes: %v != %v",
+ ii, tt.description, want, got)
+ }
+
+ // Track offset for next loop
+ offset = offset + len(check)
+ }
+
+ // Ensure last byte is always End
+ if p[len(p)-1] != byte(End) {
+ t.Fatalf("%02d: test %q, missing End byte", i, tt.description)
+ }
+ }
+}
+
+func TestPacketParseOptions(t *testing.T) {
+ for i, tt := range optionsTests {
+ // Set up new packet, apply options from slice
+ p := NewPacket(BootRequest)
+ for _, o := range tt.options {
+ p.AddOption(o.Code, o.Value)
+ }
+
+ // Parse options, verify all options are present
+ options := p.ParseOptions()
+ for _, o := range tt.options {
+ var found bool
+
+ // Search for expected option in result map
+ for k, v := range options {
+ if o.Code == k && bytes.Equal(o.Value, v) {
+ found = true
+ break
+ }
+ }
+
+ // Pad option is not parsed, but check all others
+ if !found && o.Code != Pad {
+ t.Fatalf("%02d: test %q, did not find option: %v",
+ i, tt.description, o)
+ }
+ }
+ }
+}
+
+func TestPacketStripOptions(t *testing.T) {
+ for i, tt := range optionsTests {
+ // Set up new packet, apply options from slice
+ p := NewPacket(BootRequest)
+ for _, o := range tt.options {
+ p.AddOption(o.Code, o.Value)
+ }
+
+ // Strip all options, verify options are gone
+ p.StripOptions()
+ if !bytes.Equal(p, NewPacket(BootRequest)) {
+ t.Fatalf("%02d: test %q, options stripped, but packet contained extra data",
+ i, tt.description)
+ }
+ }
+}
+
+func TestPacketPadToMinSize(t *testing.T) {
+ var tests = []struct {
+ before int
+ after int
+ }{
+ {
+ before: 0,
+ after: 272,
+ },
+ {
+ before: 100,
+ after: 272,
+ },
+ {
+ before: 300,
+ after: 300,
+ },
+ {
+ before: 1024,
+ after: 1024,
+ },
+ }
+
+ for i, tt := range tests {
+ p := make(Packet, tt.before)
+ p.PadToMinSize()
+
+ if want, got := tt.after, len(p); want != got {
+ t.Fatalf("%02d: before %d, unexpected padded length: %d != %d",
+ i, tt.before, want, got)
+ }
+ }
+}
+
+func TestRequestPacket(t *testing.T) {
+ var tests = []struct {
+ description string
+ mt MessageType
+ chAddr net.HardwareAddr
+ cIAddr net.IP
+ xId []byte
+ broadcast bool
+ options []Option
+ }{
+ {
+ description: "discover request",
+ mt: Discover,
+ chAddr: net.HardwareAddr{1, 35, 69, 103, 117, 171}, // 01:23:45:67:89:ab
+ cIAddr: net.IP([]byte{192, 168, 1, 1}),
+ xId: []byte{0, 1, 2, 3},
+ broadcast: true,
+ options: nil,
+ },
+ {
+ description: "request request",
+ mt: Request,
+ chAddr: net.HardwareAddr{222, 173, 190, 239, 222, 173}, // de:ad:be:ef:de:ad
+ xId: []byte{4, 5, 6, 7},
+ broadcast: false,
+ options: oneOptionSlice,
+ },
+ {
+ description: "decline request",
+ mt: Decline,
+ chAddr: net.HardwareAddr{255, 255, 255, 255, 255, 255}, // ff:ff:ff:ff:ff:ff
+ xId: []byte{8, 9, 10, 11},
+ broadcast: true,
+ options: twoOptionsSlice,
+ },
+ }
+
+ for i, tt := range tests {
+ // Compare our basic test implementation's packet against the library's
+ // implementation
+ want := newRequestPacket(tt.mt, tt.chAddr, tt.cIAddr, tt.xId, tt.broadcast, tt.options)
+ got := RequestPacket(tt.mt, tt.chAddr, tt.cIAddr, tt.xId, tt.broadcast, tt.options)
+
+ if !bytes.Equal(want, got) {
+ t.Fatalf("%02d: RequestPacket(), test %q, unexpected result: %v != %v",
+ i, tt.description, want, got)
+ }
+ }
+}
+
+func TestReplyPacket(t *testing.T) {
+ var tests = []struct {
+ description string
+ mt MessageType
+ serverId net.IP
+ yIAddr net.IP
+ leaseDuration time.Duration
+ options []Option
+ }{
+ {
+ description: "offer reply",
+ mt: Offer,
+ serverId: []byte{192, 168, 1, 1},
+ yIAddr: []byte{192, 168, 1, 1},
+ leaseDuration: 60 * time.Second,
+ options: nil,
+ },
+ {
+ description: "ACK reply",
+ mt: ACK,
+ serverId: []byte{10, 0, 0, 1},
+ yIAddr: []byte{192, 168, 1, 1},
+ leaseDuration: 10 * time.Second,
+ options: oneOptionSlice,
+ },
+ {
+ description: "NAK reply",
+ mt: NAK,
+ serverId: []byte{8, 8, 8, 8},
+ yIAddr: []byte{8, 8, 4, 4},
+ leaseDuration: 3600 * time.Second,
+ options: twoOptionsSlice,
+ },
+ }
+
+ for i, tt := range tests {
+ // Compare our basic test implementation's packet against the library's
+ // implementation
+ req := NewPacket(BootRequest)
+ want := newReplyPacket(req, tt.mt, tt.serverId, tt.yIAddr, tt.leaseDuration, tt.options)
+ got := ReplyPacket(req, tt.mt, tt.serverId, tt.yIAddr, tt.leaseDuration, tt.options)
+
+ if !bytes.Equal(want, got) {
+ t.Fatalf("%02d: ReplyPacket(), test %q, unexpected result: %v != %v",
+ i, tt.description, want, got)
+ }
+ }
+}
+
+// newPacket mimics the raw logic of NewPacket, and verifies that its
+// behavior does not change.
+func newPacket(opCode OpCode) Packet {
+ const ethernetHType = 1
+ var cookie = []byte{99, 130, 83, 99}
+
+ p := make(Packet, 241)
+ p[0] = byte(opCode)
+ p[1] = ethernetHType
+ copy(p[236:240], cookie)
+ p[240] = byte(End)
+
+ return p
+}
+
+// newRequestPacket mimics the raw logic of RequestPacket, and verifies that
+// its behavior does not change.
+func newRequestPacket(mt MessageType, chAddr net.HardwareAddr, cIAddr net.IP, xId []byte, broadcast bool, options []Option) Packet {
+ // Craft packet using our test method
+ p := newPacket(BootRequest)
+
+ // SetCHAddr
+ copy(p[28:44], chAddr)
+ p[2] = byte(len(chAddr))
+
+ // SetXId
+ copy(p[4:8], xId)
+
+ // SetCIAddr
+ if cIAddr != nil {
+ copy(net.IP(p[12:16]), cIAddr.To4())
+ }
+
+ // SetBroadcast
+ if broadcast {
+ p[10:12][0] ^= 128
+ }
+
+ // AddOption already tested, so no need to duplicate the logic
+ p.AddOption(OptionDHCPMessageType, []byte{byte(mt)})
+ for _, o := range options {
+ p.AddOption(o.Code, o.Value)
+ }
+
+ // PadToMinSize already tested
+ p.PadToMinSize()
+
+ return p
+}
+
+// newReplyPacket mimics the raw logic of ReplyPacket, and verifies that
+// its behavior does not change.
+func newReplyPacket(req Packet, mt MessageType, serverId, yIAddr net.IP, leaseDuration time.Duration, options []Option) Packet {
+ // Craft packet using our test method
+ p := newPacket(BootReply)
+
+ // SetXId
+ copy(p[4:8], req[4:8])
+
+ // SetFlags
+ copy(p[10:22], req[10:12])
+
+ // SetYIAddr
+ copy(p[16:20], yIAddr)
+
+ // SetGIAddr
+ copy(p[24:28], req[24:28])
+
+ // SetCHAddr
+ hLen := req[2]
+ if hLen > 16 {
+ hLen = 16
+ }
+ c := make([]byte, hLen)
+ copy(c, p[28:28+hLen])
+
+ copy(p[28:44], c)
+ p[2] = byte(len(c))
+
+ // SetSecs
+ copy(p[8:10], req[8:10])
+
+ // AddOption already tested, so no need to duplicate the logic
+ p.AddOption(OptionDHCPMessageType, []byte{byte(mt)})
+ p.AddOption(OptionServerIdentifier, []byte(serverId))
+ p.AddOption(OptionIPAddressLeaseTime, OptionsLeaseTime(leaseDuration))
+ for _, o := range options {
+ p.AddOption(o.Code, o.Value)
+ }
+
+ // PadToMinSize already tested
+ p.PadToMinSize()
+
+ return p
+}
+
+// oneOptionSlice is a test helper of []Option with a single
+// Option.
+var oneOptionSlice = []Option{
+ Option{
+ Code: OptionSubnetMask,
+ Value: []byte{255, 255, 255, 0},
+ },
+}
+
+// twoOptionSlice is a test helper of []Option with two
+// Option values.
+var twoOptionsSlice = []Option{
+ Option{
+ Code: OptionSubnetMask,
+ Value: []byte{255, 255, 255, 0},
+ },
+ Option{
+ Code: OptionDomainNameServer,
+ Value: []byte{8, 8, 8, 8},
+ },
+}
+
+// optionsTests are tests used when applying and stripping Options
+// from Packets.
+var optionsTests = []struct {
+ description string
+ options []Option
+}{
+ {
+ description: "nil options",
+ options: nil,
+ },
+ {
+ description: "empty options",
+ options: []Option{},
+ },
+ {
+ description: "padding option",
+ options: []Option{
+ Option{
+ Code: Pad,
+ },
+ },
+ },
+ {
+ description: "one option",
+ options: oneOptionSlice,
+ },
+ {
+ description: "two options",
+ options: twoOptionsSlice,
+ },
+ {
+ description: "four options",
+ options: []Option{
+ Option{
+ Code: OptionSubnetMask,
+ Value: []byte{255, 255, 255, 0},
+ },
+ Option{
+ Code: OptionDomainNameServer,
+ Value: []byte{8, 8, 8, 8},
+ },
+ Option{
+ Code: OptionTimeServer,
+ Value: []byte{127, 0, 0, 1},
+ },
+ Option{
+ Code: OptionMessage,
+ Value: []byte{'h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd'},
+ },
+ },
+ },
+}
Debdiff
[The following lists of changes regard files as different if they have different names, permissions or owners.]
Files in second set of .debs but not in first
-rw-r--r-- root/root /usr/share/gocode/src/github.com/d2g/dhcp4/helpers_test.go -rw-r--r-- root/root /usr/share/gocode/src/github.com/d2g/dhcp4/packet_test.go
No differences were encountered in the control files