netconfig: write /etc/resolv.conf

This commit is contained in:
Michael Stapelberg 2018-06-03 20:47:11 +02:00
parent 48ddf81147
commit 763aa18a74
3 changed files with 37 additions and 8 deletions

View File

@ -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.

View File

@ -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 {

View File

@ -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)
}