diff -Nru golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/debian/changelog golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/debian/changelog --- golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/debian/changelog 2020-06-19 08:12:44.000000000 +0000 +++ golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/debian/changelog 2020-07-10 14:33:16.000000000 +0000 @@ -1,3 +1,9 @@ +golang-github-insomniacslk-dhcp (0.0~git20200621.d74cd86-1) unstable; urgency=medium + + * New upstream snapshot + + -- Shengjing Zhu Fri, 10 Jul 2020 22:33:16 +0800 + golang-github-insomniacslk-dhcp (0.0~git20200420.ed3125c-1) unstable; urgency=medium * Initial release (Closes: #963113) diff -Nru golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/dhcpv4/dhcpv4.go golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/dhcpv4/dhcpv4.go --- golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/dhcpv4/dhcpv4.go 2020-04-30 19:24:52.000000000 +0000 +++ golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/dhcpv4/dhcpv4.go 2020-07-10 14:30:30.000000000 +0000 @@ -144,6 +144,7 @@ d := DHCPv4{ OpCode: OpcodeBootRequest, HWType: iana.HWTypeEthernet, + ClientHWAddr: make(net.HardwareAddr, 6), HopCount: 0, TransactionID: xid, NumSeconds: 0, @@ -476,9 +477,6 @@ // HwAddrLen hlen := uint8(len(d.ClientHWAddr)) - if hlen == 0 && d.HWType == iana.HWTypeEthernet { - hlen = 6 - } buf.Write8(hlen) buf.Write8(d.HopCount) buf.WriteBytes(d.TransactionID[:]) @@ -492,13 +490,11 @@ copy(buf.WriteN(16), d.ClientHWAddr) var sname [64]byte - copy(sname[:], []byte(d.ServerHostName)) - sname[len(d.ServerHostName)] = 0 + copy(sname[:63], []byte(d.ServerHostName)) buf.WriteBytes(sname[:]) var file [128]byte - copy(file[:], []byte(d.BootFileName)) - file[len(d.BootFileName)] = 0 + copy(file[:127], []byte(d.BootFileName)) buf.WriteBytes(file[:]) // The magic cookie. diff -Nru golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/dhcpv4/dhcpv4_test.go golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/dhcpv4/dhcpv4_test.go --- golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/dhcpv4/dhcpv4_test.go 2020-04-30 19:24:52.000000000 +0000 +++ golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/dhcpv4/dhcpv4_test.go 2020-07-10 14:30:30.000000000 +0000 @@ -3,6 +3,8 @@ import ( "bytes" "net" + "strconv" + "strings" "testing" "github.com/insomniacslk/dhcp/iana" @@ -80,16 +82,18 @@ // above } -func TestFromBytesZeroLength(t *testing.T) { - data := []byte{} - _, err := FromBytes(data) - require.Error(t, err) -} - -func TestFromBytesShortLength(t *testing.T) { - data := []byte{1, 1, 6, 0} - _, err := FromBytes(data) - require.Error(t, err) +func TestFromBytesGenericInvalid(t *testing.T) { + data := [][]byte{ + {}, + {1, 1, 6, 0}, + } + t.Parallel() + for i, packet := range data { + t.Run(strconv.Itoa(i), func(t *testing.T) { + _, err := FromBytes(packet) + require.Error(t, err) + }) + } } func TestFromBytesInvalidOptions(t *testing.T) { @@ -178,6 +182,17 @@ require.Equal(t, expected, got) } +func TestToBytesStringTooLong(t *testing.T) { + d, err := New() + if err != nil { + t.Fatal(err) + } + d.ServerHostName = strings.Repeat("a", 256) + d.BootFileName = strings.Repeat("a", 256) + + require.NotPanics(t, func() { _ = d.ToBytes() }) +} + func TestGetOption(t *testing.T) { d, err := New() if err != nil { @@ -339,7 +354,7 @@ " your IP: 0.0.0.0\n" + " server IP: 0.0.0.0\n" + " gateway IP: 0.0.0.0\n" + - " client MAC: \n" + + " client MAC: 00:00:00:00:00:00\n" + " server hostname: \n" + " bootfile name: \n" + " options:\n" + diff -Nru golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/dhcpv4/fuzz.go golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/dhcpv4/fuzz.go --- golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/dhcpv4/fuzz.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/dhcpv4/fuzz.go 2020-07-10 14:30:30.000000000 +0000 @@ -0,0 +1,41 @@ +// +build gofuzz + +package dhcpv4 + +import ( + "fmt" + "reflect" +) + +// Fuzz is the entrypoint for go-fuzz +func Fuzz(data []byte) int { + msg, err := FromBytes(data) + if err != nil { + return 0 + } + + serialized := msg.ToBytes() + + // Compared to dhcpv6, dhcpv4 has padding and fixed-size fields containing + // variable-length data; We can't expect the library to output byte-for-byte + // identical packets after a round-trip. + // Instead, we check that after a round-trip, the packet reserializes to the + // same internal representation + rtMsg, err := FromBytes(serialized) + + if err != nil || !reflect.DeepEqual(msg, rtMsg) { + fmt.Printf("Input: %x\n", data) + fmt.Printf("Round-trip: %x\n", serialized) + fmt.Println("Message: ", msg.Summary()) + fmt.Printf("Go repr: %#v\n", msg) + fmt.Println("Reserialized: ", rtMsg.Summary()) + fmt.Printf("Go repr: %#v\n", rtMsg) + if err != nil { + fmt.Printf("Got error while reserializing: %v\n", err) + panic("round-trip error: " + err.Error()) + } + panic("round-trip different: " + msg.Summary()) + } + + return 1 +} diff -Nru golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/dhcpv4/option_routes.go golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/dhcpv4/option_routes.go --- golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/dhcpv4/option_routes.go 2020-04-30 19:24:52.000000000 +0000 +++ golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/dhcpv4/option_routes.go 2020-07-10 14:30:30.000000000 +0000 @@ -38,6 +38,9 @@ // Unmarshal implements uio.Unmarshaler. func (r *Route) Unmarshal(buf *uio.Lexer) error { maskSize := buf.Read8() + if maskSize > 32 { + return fmt.Errorf("invalid mask length %d in route option", maskSize) + } r.Dest = &net.IPNet{ IP: make([]byte, net.IPv4len), Mask: net.CIDRMask(int(maskSize), 32), diff -Nru golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/dhcpv4/option_routes_test.go golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/dhcpv4/option_routes_test.go --- golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/dhcpv4/option_routes_test.go 2020-04-30 19:24:52.000000000 +0000 +++ golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/dhcpv4/option_routes_test.go 2020-07-10 14:30:30.000000000 +0000 @@ -16,9 +16,9 @@ func TestParseRoutes(t *testing.T) { for _, tt := range []struct { - p []byte - want Routes - err error + p []byte + want Routes + wantErr bool }{ { p: []byte{32, 10, 2, 3, 4, 0, 0, 0, 0}, @@ -51,10 +51,14 @@ }, }, }, + { + p: []byte{64, 10, 2, 3, 4}, + wantErr: true, // Mask length 64 > 32 + }, } { var r Routes - if err := r.FromBytes(tt.p); err != tt.err { - t.Errorf("FromBytes(%v) = %v, want %v", tt.p, err, tt.err) + if err := r.FromBytes(tt.p); (err != nil) != tt.wantErr { + t.Errorf("FromBytes(%v) Unexpected error state: %v", tt.p, err) } if !reflect.DeepEqual(r, tt.want) { diff -Nru golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/dhcpv4/options.go golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/dhcpv4/options.go --- golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/dhcpv4/options.go 2020-04-30 19:24:52.000000000 +0000 +++ golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/dhcpv4/options.go 2020-07-10 14:30:30.000000000 +0000 @@ -185,12 +185,20 @@ code := uint8(c) // Even if the End option is in there, don't marshal it until // the end. - if code == optEnd { + // Don't write padding either, since the options are sorted + // it would always be written first which isn't useful + if code == optEnd || code == optPad { continue } data := o[code] + // Ensure even 0-length options are written out + if len(data) == 0 { + b.Write8(code) + b.Write8(0) + continue + } // RFC 3396: If more than 256 bytes of data are given, the // option is simply listed multiple times. for len(data) > 0 { diff -Nru golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/dhcpv4/options_test.go golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/dhcpv4/options_test.go --- golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/dhcpv4/options_test.go 2020-04-30 19:24:52.000000000 +0000 +++ golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/dhcpv4/options_test.go 2020-07-10 14:30:30.000000000 +0000 @@ -194,9 +194,25 @@ 5, 1, 10, ), }, + { + // Test 0-length options + opts: Options{ + 80: []byte{}, + }, + want: []byte{80, 0}, + }, + { + // Test special options, handled by the message marshalling code + // and ignored by the options marshalling code + opts: Options{ + 0: []byte{}, // Padding + 255: []byte{}, // End of options + }, + want: nil, // not written out + }, } { t.Run(fmt.Sprintf("Test %02d", i), func(t *testing.T) { - require.Equal(t, uio.ToBigEndian(tt.opts), tt.want) + require.Equal(t, tt.want, uio.ToBigEndian(tt.opts)) }) } } diff -Nru golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/dhcpv6/dhcpv6relay.go golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/dhcpv6/dhcpv6relay.go --- golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/dhcpv6/dhcpv6relay.go 2020-04-30 19:24:52.000000000 +0000 +++ golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/dhcpv6/dhcpv6relay.go 2020-07-10 14:30:30.000000000 +0000 @@ -5,6 +5,7 @@ "fmt" "net" + "github.com/insomniacslk/dhcp/iana" "github.com/u-root/u-root/pkg/uio" ) @@ -54,6 +55,19 @@ return nil } +// ClientLinkLayerAddress returns the Hardware Type and +// Link Layer Address of the requesting client in this relay message. +func (ro RelayOptions) ClientLinkLayerAddress() (iana.HWType, net.HardwareAddr) { + opt := ro.Options.GetOne(OptionClientLinkLayerAddr) + if opt == nil { + return 0, nil + } + if lla, ok := opt.(*optClientLinkLayerAddress); ok { + return lla.LinkLayerType, lla.LinkLayerAddress + } + return 0, nil +} + // RelayMessage is a DHCPv6 relay agent message as defined by RFC 3315 Section // 7. type RelayMessage struct { diff -Nru golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/dhcpv6/modifiers.go golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/dhcpv6/modifiers.go --- golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/dhcpv6/modifiers.go 2020-04-30 19:24:52.000000000 +0000 +++ golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/dhcpv6/modifiers.go 2020-07-10 14:30:30.000000000 +0000 @@ -152,3 +152,9 @@ } } } + +// WithClientLinkLayerAddress adds or updates the ClientLinkLayerAddress +// option with provided HWType and HWAddress on a DHCPv6 packet +func WithClientLinkLayerAddress(ht iana.HWType, lla net.HardwareAddr) Modifier { + return WithOption(OptClientLinkLayerAddress(ht, lla)) +} diff -Nru golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/dhcpv6/modifiers_test.go golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/dhcpv6/modifiers_test.go --- golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/dhcpv6/modifiers_test.go 2020-04-30 19:24:52.000000000 +0000 +++ golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/dhcpv6/modifiers_test.go 2020-07-10 14:30:30.000000000 +0000 @@ -121,3 +121,16 @@ require.Equal(t, 1, len(opt)) require.Equal(t, OptionIAPD, opt[0].Code()) } + +func TestWithClientLinkLayerAddress(t *testing.T) { + var d RelayMessage + mac, _ := net.ParseMAC("a4:83:e7:e3:df:88") + WithClientLinkLayerAddress(iana.HWTypeEthernet, mac)(&d) + + opt := d.Options.GetOne(OptionClientLinkLayerAddr) + require.Equal(t, OptionClientLinkLayerAddr, opt.Code()) + + llt, lla := d.Options.ClientLinkLayerAddress() + require.Equal(t, iana.HWTypeEthernet, llt) + require.Equal(t, mac, lla) +} diff -Nru golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/dhcpv6/option_clientlinklayeraddress.go golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/dhcpv6/option_clientlinklayeraddress.go --- golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/dhcpv6/option_clientlinklayeraddress.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/dhcpv6/option_clientlinklayeraddress.go 2020-07-10 14:30:30.000000000 +0000 @@ -0,0 +1,47 @@ +package dhcpv6 + +import ( + "fmt" + "net" + + "github.com/insomniacslk/dhcp/iana" + "github.com/u-root/u-root/pkg/uio" +) + +// OptClientLinkLayerAddress implements OptionClientLinkLayerAddr option. +// https://tools.ietf.org/html/rfc6939 +func OptClientLinkLayerAddress(ht iana.HWType, lla net.HardwareAddr) *optClientLinkLayerAddress { + return &optClientLinkLayerAddress{LinkLayerType: ht, LinkLayerAddress: lla} +} + +type optClientLinkLayerAddress struct { + LinkLayerType iana.HWType + LinkLayerAddress net.HardwareAddr +} + +// Code returns the option code. +func (op *optClientLinkLayerAddress) Code() OptionCode { + return OptionClientLinkLayerAddr +} + +// ToBytes serializes the option and returns it as a sequence of bytes +func (op *optClientLinkLayerAddress) ToBytes() []byte { + buf := uio.NewBigEndianBuffer(nil) + buf.Write16(uint16(op.LinkLayerType)) + buf.WriteBytes(op.LinkLayerAddress) + return buf.Data() +} + +func (op *optClientLinkLayerAddress) String() string { + return fmt.Sprintf("ClientLinkLayerAddress: Type=%s LinkLayerAddress=%s", op.LinkLayerType, op.LinkLayerAddress) +} + +// parseOptClientLinkLayerAddress deserializes from bytes +// to build an optClientLinkLayerAddress structure. +func parseOptClientLinkLayerAddress(data []byte) (*optClientLinkLayerAddress, error) { + var opt optClientLinkLayerAddress + buf := uio.NewBigEndianBuffer(data) + opt.LinkLayerType = iana.HWType(buf.Read16()) + opt.LinkLayerAddress = buf.ReadAll() + return &opt, buf.FinError() +} diff -Nru golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/dhcpv6/option_clientlinklayeraddress_test.go golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/dhcpv6/option_clientlinklayeraddress_test.go --- golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/dhcpv6/option_clientlinklayeraddress_test.go 1970-01-01 00:00:00.000000000 +0000 +++ golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/dhcpv6/option_clientlinklayeraddress_test.go 2020-07-10 14:30:30.000000000 +0000 @@ -0,0 +1,40 @@ +package dhcpv6 + +import ( + "bytes" + "net" + "testing" + + "github.com/insomniacslk/dhcp/iana" + "github.com/stretchr/testify/require" +) + +func TestParseOptClientLinkLayerAddress(t *testing.T) { + data := []byte{ + 0, 1, // LinkLayerType + 164, 131, 231, 227, 223, 136, + } + opt, err := parseOptClientLinkLayerAddress(data) + + require.NoError(t, err) + require.Equal(t, OptionClientLinkLayerAddr, opt.Code()) + require.Equal(t, iana.HWTypeEthernet, opt.LinkLayerType) + require.Equal(t, net.HardwareAddr(data[2:]), opt.LinkLayerAddress) + require.Equal(t, "ClientLinkLayerAddress: Type=Ethernet LinkLayerAddress=a4:83:e7:e3:df:88", opt.String()) +} + +func TestOptClientLinkLayerAddressToBytes(t *testing.T) { + mac, _ := net.ParseMAC("a4:83:e7:e3:df:88") + opt := optClientLinkLayerAddress{ + LinkLayerType: iana.HWTypeEthernet, + LinkLayerAddress: mac, + } + want := []byte{ + 0, 1, // LinkLayerType + 164, 131, 231, 227, 223, 136, + } + b := opt.ToBytes() + if !bytes.Equal(b, want) { + t.Fatalf("opt.ToBytes()=%v, want %v", b, want) + } +} diff -Nru golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/dhcpv6/options.go golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/dhcpv6/options.go --- golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/dhcpv6/options.go 2020-04-30 19:24:52.000000000 +0000 +++ golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/dhcpv6/options.go 2020-07-10 14:30:30.000000000 +0000 @@ -87,6 +87,8 @@ var o OptNetworkInterfaceID err = o.FromBytes(optData) opt = &o + case OptionClientLinkLayerAddr: + opt, err = parseOptClientLinkLayerAddress(optData) case OptionDHCPv4Msg: opt, err = ParseOptDHCPv4Msg(optData) case OptionDHCP4oDHCP6Server: diff -Nru golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/.travis/linters.sh golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/.travis/linters.sh --- golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/.travis/linters.sh 2020-04-30 19:24:52.000000000 +0000 +++ golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/.travis/linters.sh 2020-07-10 14:30:30.000000000 +0000 @@ -1,5 +1,6 @@ #!/usr/bin/env bash -go get github.com/golangci/golangci-lint/cmd/golangci-lint -go install github.com/golangci/golangci-lint/cmd/golangci-lint -golangci-lint run +set -e + +GO111MODULE=on go get github.com/golangci/golangci-lint/cmd/golangci-lint +$GOPATH/bin/golangci-lint run diff -Nru golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/.travis.yml golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/.travis.yml --- golang-github-insomniacslk-dhcp-0.0~git20200420.ed3125c/.travis.yml 2020-04-30 19:24:52.000000000 +0000 +++ golang-github-insomniacslk-dhcp-0.0~git20200621.d74cd86/.travis.yml 2020-07-10 14:30:30.000000000 +0000 @@ -3,9 +3,8 @@ sudo: required go: - - "1.11" - - "1.12" - "1.13" + - "1.14" env: - TEST_SUITE=unit