diff --git a/cmd/netconfigd/netconfigd.go b/cmd/netconfigd/netconfigd.go index 292bffc..dc0fce3 100644 --- a/cmd/netconfigd/netconfigd.go +++ b/cmd/netconfigd/netconfigd.go @@ -21,7 +21,7 @@ func logic() error { ch := make(chan os.Signal, 1) signal.Notify(ch, syscall.SIGUSR1) for { - err := netconfig.Apply("/perm/") + err := netconfig.Apply("/perm/", "/") // Notify gokrazy about new addresses (netconfig.Apply might have // modified state before returning an error) so that listeners can be // updated. diff --git a/integrationnetconfig_test.go b/integrationnetconfig_test.go index 0b50d43..b06f325 100644 --- a/integrationnetconfig_test.go +++ b/integrationnetconfig_test.go @@ -19,6 +19,11 @@ const goldenInterfaces = ` { "hardware_addr": "02:73:53:00:ca:fe", "name": "uplink0" + }, + { + "hardware_addr": "02:73:53:00:b0:0c", + "name": "lan0", + "addr": "192.168.42.1/24" } ] } @@ -73,10 +78,22 @@ func TestNetconfig(t *testing.T) { } } - if err := netconfig.Apply(tmp); err != nil { + if err := os.MkdirAll(filepath.Join(tmp, "root", "etc"), 0755); err != nil { + t.Fatal(err) + } + + if err := netconfig.Apply(tmp, filepath.Join(tmp, "root")); err != nil { t.Fatalf("netconfig.Apply: %v", err) } + b, err := ioutil.ReadFile(filepath.Join(tmp, "root", "etc", "resolv.conf")) + if err != nil { + t.Fatal(err) + } + if got, want := strings.TrimSpace(string(b)), "nameserver 192.168.42.1"; got != want { + t.Errorf("/etc/resolv.conf: got %q, want %q", got, want) + } + return } const ns = "ns1" // name of the network namespace to use for this test @@ -90,6 +107,7 @@ func TestNetconfig(t *testing.T) { exec.Command("ip", "netns", "exec", ns, "ip", "link", "add", "dummy0", "type", "dummy"), exec.Command("ip", "netns", "exec", ns, "ip", "link", "add", "lan0", "type", "dummy"), exec.Command("ip", "netns", "exec", ns, "ip", "link", "set", "dummy0", "address", "02:73:53:00:ca:fe"), + exec.Command("ip", "netns", "exec", ns, "ip", "link", "set", "lan0", "address", "02:73:53:00:b0:0c"), } for _, cmd := range nsSetup { diff --git a/internal/netconfig/netconfig.go b/internal/netconfig/netconfig.go index 33403b0..f6c0109 100644 --- a/internal/netconfig/netconfig.go +++ b/internal/netconfig/netconfig.go @@ -4,7 +4,6 @@ import ( "encoding/json" "fmt" "io/ioutil" - "log" "net" "os" "path/filepath" @@ -16,8 +15,11 @@ import ( "router7/internal/dhcp4" "router7/internal/dhcp6" + "router7/internal/teelogger" ) +var log = teelogger.NewConsole() + func subnetMaskSize(mask string) (int, error) { parts := strings.Split(mask, ".") if got, want := len(parts), 4; got != want { @@ -154,7 +156,7 @@ type InterfaceConfig struct { Interfaces []InterfaceDetails `json:"interfaces"` } -func applyInterfaces(dir string) error { +func applyInterfaces(dir, root string) error { b, err := ioutil.ReadFile(filepath.Join(dir, "interfaces.json")) if err != nil { return err @@ -180,11 +182,9 @@ func applyInterfaces(dir string) error { continue // not a configurable interface (e.g. sit0) } log.Printf("no config for hardwareattr %s", addr) - ioutil.WriteFile("/dev/console", []byte(fmt.Sprintf("no config for hardwareattr %s\n", addr)), 0600) continue } log.Printf("apply details %+v", details) - ioutil.WriteFile("/dev/console", []byte(fmt.Sprintf("apply %+v\n", details)), 0600) if attr.Name != details.Name { if err := netlink.LinkSetName(l, details.Name); err != nil { return fmt.Errorf("LinkSetName(%q): %v", details.Name, err) @@ -208,6 +208,17 @@ func applyInterfaces(dir string) error { if err := netlink.AddrReplace(l, addr); err != nil { return fmt.Errorf("AddrReplace(%s, %v): %v", attr.Name, addr, err) } + + if details.Name == "lan0" { + b := []byte("nameserver " + addr.IP.String() + "\n") + fn := filepath.Join(root, "etc", "resolv.conf") + if err := os.Remove(fn); err != nil && !os.IsNotExist(err) { + return err + } + if err := ioutil.WriteFile(fn, b, 0644); err != nil { + return err + } + } } } return nil @@ -254,10 +265,10 @@ func applySysctl() error { return nil } -func Apply(dir string) error { +func Apply(dir, root string) error { // TODO: split into two parts: delay the up until later - if err := applyInterfaces(dir); err != nil { + if err := applyInterfaces(dir, root); err != nil { return fmt.Errorf("interfaces: %v", err) }