dhcp: support multiple DNS server addresses
Change-Id: I1251a17d83c782a58a7bd1d44a6c5730bf1e84a1
diff --git a/dhcp/dhcp.go b/dhcp/dhcp.go
index 35a7e5d..de0f65f 100644
--- a/dhcp/dhcp.go
+++ b/dhcp/dhcp.go
@@ -16,12 +16,12 @@
// Config is standard DHCP configuration.
type Config struct {
- Error error
- ServerAddress tcpip.Address // address of the server
- SubnetMask tcpip.AddressMask // client address subnet mask
- Gateway tcpip.Address // client default gateway
- DomainNameServer tcpip.Address // client domain name server
- LeaseLength time.Duration // length of the address lease
+ Error error
+ ServerAddress tcpip.Address // address of the server
+ SubnetMask tcpip.AddressMask // client address subnet mask
+ Gateway tcpip.Address // client default gateway
+ DNS []tcpip.Address // client domain name servers
+ LeaseLength time.Duration // length of the address lease
}
func (cfg *Config) decode(opts []option) error {
@@ -42,8 +42,12 @@
case optDefaultGateway:
cfg.Gateway = tcpip.Address(b)
case optDomainNameServer:
- // TODO(crawshaw): handle multiple DNS servers
- cfg.DomainNameServer = tcpip.Address(b[:4])
+ for ; len(b) > 0; b = b[4:] {
+ if len(b) < 4 {
+ return fmt.Errorf("DNS bad length: %d", len(b))
+ }
+ cfg.DNS = append(cfg.DNS, tcpip.Address(b[:4]))
+ }
}
}
return nil
@@ -59,8 +63,12 @@
if cfg.Gateway != "" {
opts = append(opts, option{optDefaultGateway, []byte(cfg.Gateway)})
}
- if cfg.DomainNameServer != "" {
- opts = append(opts, option{optDomainNameServer, []byte(cfg.DomainNameServer)})
+ if len(cfg.DNS) > 0 {
+ dns := make([]byte, 0, 4*len(cfg.DNS))
+ for _, addr := range cfg.DNS {
+ dns = append(dns, addr...)
+ }
+ opts = append(opts, option{optDomainNameServer, dns})
}
if l := cfg.LeaseLength / time.Second; l != 0 {
v := make([]byte, 4)
diff --git a/dhcp/dhcp_test.go b/dhcp/dhcp_test.go
index 9a23f78..92c5c41 100644
--- a/dhcp/dhcp_test.go
+++ b/dhcp/dhcp_test.go
@@ -63,11 +63,13 @@
clientAddrs := []tcpip.Address{"\xc0\xa8\x03\x02", "\xc0\xa8\x03\x03"}
serverCfg := Config{
- ServerAddress: serverAddr,
- SubnetMask: "\xff\xff\xff\x00",
- Gateway: "\xc0\xa8\x03\xF0",
- DomainNameServer: "\x08\x08\x08\x08",
- LeaseLength: 24 * time.Hour,
+ ServerAddress: serverAddr,
+ SubnetMask: "\xff\xff\xff\x00",
+ Gateway: "\xc0\xa8\x03\xF0",
+ DNS: []tcpip.Address{
+ "\x08\x08\x08\x08", "\x08\x08\x04\x04",
+ },
+ LeaseLength: 24 * time.Hour,
}
serverCtx, cancel := context.WithCancel(context.Background())
defer cancel()
@@ -107,21 +109,36 @@
t.Errorf("c.Addr()=%s, want=%s", got, want)
}
- if got, want := c0.Config(), serverCfg; got != want {
+ if got, want := c0.Config(), serverCfg; !equalConfig(got, want) {
t.Errorf("client config:\n\t%#+v\nwant:\n\t%#+v", got, want)
}
}
+func equalConfig(c0, c1 Config) bool {
+ if c0.Error != c1.Error || c0.ServerAddress != c1.ServerAddress || c0.SubnetMask != c1.SubnetMask || c0.Gateway != c1.Gateway || c0.LeaseLength != c1.LeaseLength {
+ return false
+ }
+ if len(c0.DNS) != len(c1.DNS) {
+ return false
+ }
+ for i := 0; i < len(c0.DNS); i++ {
+ if c0.DNS[i] != c1.DNS[i] {
+ return false
+ }
+ }
+ return true
+}
+
func TestRenew(t *testing.T) {
s := createStack(t)
clientAddrs := []tcpip.Address{"\xc0\xa8\x03\x02"}
serverCfg := Config{
- ServerAddress: serverAddr,
- SubnetMask: "\xff\xff\xff\x00",
- Gateway: "\xc0\xa8\x03\xF0",
- DomainNameServer: "\x08\x08\x08\x08",
- LeaseLength: 1 * time.Second,
+ ServerAddress: serverAddr,
+ SubnetMask: "\xff\xff\xff\x00",
+ Gateway: "\xc0\xa8\x03\xF0",
+ DNS: []tcpip.Address{"\x08\x08\x08\x08"},
+ LeaseLength: 1 * time.Second,
}
serverCtx, cancel := context.WithCancel(context.Background())
defer cancel()