Pull request: dhcpd: fix ip option parsing

Merge in DNS/adguard-home from 2688-dhcp-opt-ip to master

Updates #2688.

Squashed commit of the following:

commit e17e003a3a61c1f4ed55617bb61df721cbca12c1
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Tue Feb 16 17:10:32 2021 +0300

    dhcpd: fix ip option parsing
This commit is contained in:
Ainar Garipov 2021-02-16 17:58:42 +03:00
parent f68f6c9b37
commit e32c18faab
3 changed files with 42 additions and 12 deletions

View File

@ -17,6 +17,14 @@ and this project adheres to
## [v0.105.2] - 2021-02-24 ## [v0.105.2] - 2021-02-24
--> -->
### Fixed
- Wrong parsing of DHCP options of the `ip` type ([#2688]).
[#2688]: https://github.com/AdguardTeam/AdGuardHome/issues/2688
## [v0.105.1] - 2021-02-15 ## [v0.105.1] - 2021-02-15
### Changed ### Changed

View File

@ -293,14 +293,22 @@ func parseOptionString(s string) (uint8, []byte) {
if err != nil { if err != nil {
return 0, nil return 0, nil
} }
case "ip": case "ip":
ip := net.ParseIP(sval) ip := net.ParseIP(sval)
if ip == nil { if ip == nil {
return 0, nil return 0, nil
} }
val = ip
// Most DHCP options require IPv4, so do not put the 16-byte
// version if we can. Otherwise, the clients will receive weird
// data that looks like four IPv4 addresses.
//
// See https://github.com/AdguardTeam/AdGuardHome/issues/2688.
if ip4 := ip.To4(); ip4 != nil {
val = ip4
} else {
val = ip
}
default: default:
return 0, nil return 0, nil
} }

View File

@ -3,7 +3,6 @@
package dhcpd package dhcpd
import ( import (
"bytes"
"net" "net"
"os" "os"
"testing" "testing"
@ -130,36 +129,51 @@ func TestOptions(t *testing.T) {
testCases := []struct { testCases := []struct {
name string name string
optStr string optStr string
wantCode uint8
wantVal []byte wantVal []byte
wantCode uint8
}{{ }{{
name: "all_right_hex", name: "success_hex",
optStr: " 12 hex abcdef ", optStr: "12 hex abcdef",
wantCode: 12,
wantVal: []byte{0xab, 0xcd, 0xef}, wantVal: []byte{0xab, 0xcd, 0xef},
wantCode: 12,
}, { }, {
name: "bad_hex", name: "bad_hex",
optStr: " 12 hex abcdef1 ", optStr: "12 hex abcdefx",
wantVal: nil,
wantCode: 0, wantCode: 0,
}, { }, {
name: "all_right_ip", name: "success_ip",
optStr: "123 ip 1.2.3.4", optStr: "123 ip 1.2.3.4",
wantVal: net.IP{1, 2, 3, 4},
wantCode: 123,
}, {
name: "success_ipv6",
optStr: "123 ip ::1234",
wantVal: net.IP{
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0x12, 0x34,
},
wantCode: 123, wantCode: 123,
wantVal: net.IPv4(1, 2, 3, 4),
}, { }, {
name: "bad_code", name: "bad_code",
optStr: "256 ip 1.1.1.1", optStr: "256 ip 1.1.1.1",
wantVal: nil,
wantCode: 0, wantCode: 0,
}, { }, {
name: "negative_code", name: "negative_code",
optStr: "-1 ip 1.1.1.1", optStr: "-1 ip 1.1.1.1",
wantVal: nil,
wantCode: 0, wantCode: 0,
}, { }, {
name: "bad_ip", name: "bad_ip",
optStr: "12 ip 1.1.1.1x", optStr: "12 ip 1.1.1.1x",
wantVal: nil,
wantCode: 0, wantCode: 0,
}, { }, {
name: "bad_mode", name: "bad_mode",
wantVal: nil,
optStr: "12 x 1.1.1.1", optStr: "12 x 1.1.1.1",
wantCode: 0, wantCode: 0,
}} }}
@ -167,9 +181,9 @@ func TestOptions(t *testing.T) {
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
code, val := parseOptionString(tc.optStr) code, val := parseOptionString(tc.optStr)
require.EqualValues(t, tc.wantCode, code) require.Equal(t, tc.wantCode, code)
if tc.wantVal != nil { if tc.wantVal != nil {
assert.True(t, bytes.Equal(tc.wantVal, val)) assert.Equal(t, tc.wantVal, val)
} }
}) })
} }