diff --git a/.gitignore b/.gitignore index 8c0cf4a..73fab07 100644 --- a/.gitignore +++ b/.gitignore @@ -1,26 +1,10 @@ -# If you prefer the allow list template instead of the deny list, see community template: -# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore -# -# Binaries for programs and plugins -*.exe -*.exe~ -*.dll -*.so -*.dylib +# Generated by Cargo +# will have compiled files and executables +debug/ +target/ -# Test binary, built with `go test -c` -*.test +# These are backup files generated by rustfmt +**/*.rs.bk -# Output of the go coverage tool, specifically when used with LiteIDE -*.out - -# Dependency directories (remove the comment below to include it) -# vendor/ - -# Go workspace file -go.work - - -# Added by cargo - -/target +# MSVC Windows builds of rustc generate these, which store debugging information +*.pdb diff --git a/go.mod b/go.mod deleted file mode 100644 index 6f5765c..0000000 --- a/go.mod +++ /dev/null @@ -1,16 +0,0 @@ -module github.com/suse-edge/nm-configurator - -go 1.20 - -require ( - github.com/sirupsen/logrus v1.9.3 - github.com/stretchr/testify v1.7.0 - gopkg.in/ini.v1 v1.67.0 - gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c -) - -require ( - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect -) diff --git a/go.sum b/go.sum deleted file mode 100644 index c8704c1..0000000 --- a/go.sum +++ /dev/null @@ -1,18 +0,0 @@ -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= -gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go deleted file mode 100644 index 78e4144..0000000 --- a/main.go +++ /dev/null @@ -1,63 +0,0 @@ -package main - -import ( - "flag" - "os" - - log "github.com/sirupsen/logrus" - "github.com/suse-edge/nm-configurator/pkg/config" - "github.com/suse-edge/nm-configurator/pkg/configurator" -) - -const systemConnectionsDir = "/etc/NetworkManager/system-connections" - -func init() { - log.SetFormatter(&log.TextFormatter{ - FullTimestamp: true, - QuoteEmptyFields: true, - }) - log.SetOutput(os.Stdout) -} - -func main() { - var ( - configDir string - hostsConfigFile string - verbose bool - ) - - flag.StringVar(&configDir, "config-dir", "config", "directory storing host mapping ('host_config.yaml') and *.nmconnection files per host") - flag.StringVar(&hostsConfigFile, "hosts-config-file", "host_config.yaml", "name of the hosts config file mapping interfaces to the respective MAC addresses") - flag.BoolVar(&verbose, "verbose", false, "enables DEBUG log level") - flag.Parse() - - if verbose { - log.SetLevel(log.DebugLevel) - } - - log.Info("starting network manager configurator...") - - if err := os.MkdirAll(systemConnectionsDir, 0755); err != nil { - log.Fatalf("failed to create \"system-connections\" dir: %s", err) - } - - conf, err := config.Load(configDir, hostsConfigFile, systemConnectionsDir) - if err != nil { - log.Fatalf("failed to load static host configuration: %s", err) - } - - log.Debugf("loaded static configuration: %+v", conf) - - networkInterfaces, err := configurator.GetNetworkInterfaces() - if err != nil { - log.Fatalf("failed to list system network interfaces: %s", err) - } - - log.Debugf("fetched system network interfaces: %+v", networkInterfaces) - - c := configurator.New(conf, networkInterfaces) - if err = c.Run(); err != nil { - log.Fatalf("failed to configure network manager: %s", err) - } - log.Info("successfully configured network manager") -} diff --git a/main_test.go b/main_test.go deleted file mode 100644 index 6c38b4d..0000000 --- a/main_test.go +++ /dev/null @@ -1,69 +0,0 @@ -package main - -import ( - "os" - "path/filepath" - "strings" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "github.com/suse-edge/nm-configurator/pkg/config" - "github.com/suse-edge/nm-configurator/pkg/configurator" -) - -const ( - sourceDir = "testdata" - configFile = "host_config.yaml" - destDir = "testdata/out" -) - -func setupDestDir(t *testing.T) func(t *testing.T) { - require.NoError(t, os.MkdirAll(destDir, 0755)) - - return func(t *testing.T) { - assert.NoError(t, os.RemoveAll(destDir)) - } -} - -func TestConfigurator(t *testing.T) { - teardown := setupDestDir(t) - defer teardown(t) - - conf, err := config.Load(sourceDir, configFile, destDir) - require.Nil(t, err) - - networkInterfaces := map[string]string{ - "00:11:22:33:44:55": "eth0", - "00:11:22:33:44:56": "eth0.202", // Defined as "eth0.101" in eth0.101.nmconnection - "00:11:22:33:44:57": "eth1", - //"00:11:22:33:44:58": "bond0", Excluded on purpose, "bond0.nmconnection" should still be copied - } - - c := configurator.New(conf, networkInterfaces) - require.NoError(t, c.Run()) - - // Verify the content of the copied files. - hostDir := filepath.Join(sourceDir, "node1.example.com") - entries, err := os.ReadDir(hostDir) - require.Nil(t, err) - - assert.Len(t, entries, 4) - - for _, entry := range entries { - filename := entry.Name() - input, err := os.ReadFile(filepath.Join(hostDir, filename)) - require.Nil(t, err) - - // Adjust the name and content for the "eth0.101"->"eth0.202" edge case. - if filename == "eth0.101.nmconnection" { - filename = "eth0.202.nmconnection" - input = []byte(strings.ReplaceAll(string(input), "eth0.101", "eth0.202")) - } - - output, err := os.ReadFile(filepath.Join(destDir, filename)) - require.Nil(t, err) - - assert.Equal(t, string(input), string(output)) - } -} diff --git a/pkg/config/config.go b/pkg/config/config.go deleted file mode 100644 index 6f8c8cf..0000000 --- a/pkg/config/config.go +++ /dev/null @@ -1,62 +0,0 @@ -package config - -import ( - "fmt" - "os" - "path/filepath" - "strings" - - "gopkg.in/yaml.v3" -) - -type Config struct { - // Configuration directory storing the preconfigured *.nmconnection files per host. - SourceDir string - // Destination directory to store the final *.nmconnection files for NetworkManager. - // Default "/etc/NetworkManager/system-connections". - DestinationDir string - Hosts []*Host `yaml:"host_config"` -} - -type Host struct { - Name string `yaml:"hostname"` - Interfaces []*Interface `yaml:"interfaces"` -} - -func (h *Host) String() string { - return fmt.Sprintf("{Name: %s Interfaces: %+v}", h.Name, h.Interfaces) -} - -type Interface struct { - LogicalName string `yaml:"logical_name"` - MACAddress string `yaml:"mac_address"` -} - -func (i *Interface) String() string { - return fmt.Sprintf("{LogicalName: %s MACAddress: %s}", i.LogicalName, i.MACAddress) -} - -func Load(sourceDir, configFilename, destinationDir string) (*Config, error) { - configFile := filepath.Join(sourceDir, configFilename) - file, err := os.ReadFile(configFile) - if err != nil { - return nil, err - } - - var c Config - if err = yaml.Unmarshal(file, &c); err != nil { - return nil, err - } - - // Ensure lower case formatting. - for _, host := range c.Hosts { - for _, i := range host.Interfaces { - i.MACAddress = strings.ToLower(i.MACAddress) - } - } - - c.SourceDir = sourceDir - c.DestinationDir = destinationDir - - return &c, nil -} diff --git a/pkg/configurator/configurator.go b/pkg/configurator/configurator.go deleted file mode 100644 index 84f83b4..0000000 --- a/pkg/configurator/configurator.go +++ /dev/null @@ -1,130 +0,0 @@ -package configurator - -import ( - "errors" - "fmt" - "os" - "path/filepath" - "strings" - - log "github.com/sirupsen/logrus" - "github.com/suse-edge/nm-configurator/pkg/config" - "gopkg.in/ini.v1" -) - -const connectionFileExt = ".nmconnection" - -type Configurator struct { - config *config.Config - networkInterfaces NetworkInterfaces -} - -func New(config *config.Config, interfaces NetworkInterfaces) *Configurator { - return &Configurator{ - config: config, - networkInterfaces: interfaces, - } -} - -func (c *Configurator) Run() error { - host, err := c.identifyHost() - if err != nil { - return fmt.Errorf("identifying host: %w", err) - } - log.Infof("successfully identified host: %s", host.Name) - - if err = c.copyConnectionFiles(host); err != nil { - return fmt.Errorf("copying files: %w", err) - } - - return nil -} - -// Identify the preconfigured static host by matching the MAC address of at least one of the local network interfaces. -func (c *Configurator) identifyHost() (*config.Host, error) { - for _, host := range c.config.Hosts { - for _, i := range host.Interfaces { - if _, ok := c.networkInterfaces[i.MACAddress]; ok { - return host, nil - } - } - } - - return nil, fmt.Errorf("none of the preconfigured hosts match local NICs") -} - -// Copy all *.nmconnection files from the preconfigured host dir to the -// appropriate NetworkManager dir (default "/etc/NetworkManager/system-connections"). -func (c *Configurator) copyConnectionFiles(host *config.Host) error { - hostConfigDir := filepath.Join(c.config.SourceDir, host.Name) - dirEntries, err := os.ReadDir(hostConfigDir) - if err != nil { - return err - } - - var errs []error - - for _, entry := range dirEntries { - name := entry.Name() - if entry.IsDir() { - log.Warnf("ignoring unexpected directory: %s", name) - continue - } - - if filepath.Ext(name) != connectionFileExt { - log.Warnf("ignoring unexpected file: %s", name) - continue - } - - source := filepath.Join(hostConfigDir, name) - file, err := ini.Load(source) - if err != nil { - errs = append(errs, fmt.Errorf("loading file %s: %w", source, err)) - continue - } - - destination := filepath.Join(c.config.DestinationDir, name) - filename := strings.TrimSuffix(name, connectionFileExt) - - // Update the name and all references of the host NIC in the settings file if there is a difference from the static config. - for _, i := range host.Interfaces { - if i.LogicalName != filename { - continue - } - - interfaceName, ok := c.networkInterfaces[i.MACAddress] - if ok && interfaceName != i.LogicalName { - log.Debugf("using name '%s' for interface with MAC address '%s' instead of the preconfigured '%s'", - interfaceName, i.MACAddress, i.LogicalName) - - for _, section := range file.Sections() { - if !section.HasValue(i.LogicalName) { - continue - } - - for _, key := range section.Keys() { - if key.Value() == i.LogicalName { - key.SetValue(interfaceName) - } - } - } - - destination = fmt.Sprintf("%s/%s%s", c.config.DestinationDir, interfaceName, connectionFileExt) - } - break - } - - log.Infof("storing file %s...", destination) - if err = file.SaveTo(destination); err != nil { - errs = append(errs, fmt.Errorf("storing file %s: %w", destination, err)) - continue - } - - // Set the necessary permissions required by NetworkManager. - if err = os.Chmod(destination, 0600); err != nil { - errs = append(errs, fmt.Errorf("updating permissions for file %s: %w", destination, err)) - } - } - - return errors.Join(errs...) -} diff --git a/pkg/configurator/configurator_test.go b/pkg/configurator/configurator_test.go deleted file mode 100644 index 26806d8..0000000 --- a/pkg/configurator/configurator_test.go +++ /dev/null @@ -1,156 +0,0 @@ -package configurator - -import ( - "os" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "github.com/suse-edge/nm-configurator/pkg/config" -) - -func TestConfigurator_Run(t *testing.T) { - const destDir = "testdata/out" - require.Nil(t, os.MkdirAll(destDir, 0755)) - - defer func() { - assert.Nil(t, os.RemoveAll(destDir)) - }() - - tests := []struct { - name string - conf *config.Config - localInterfaces NetworkInterfaces - expectedErr string - }{ - { - name: "configurator fails due to none of the preconfigured hosts matching local interfaces", - conf: &config.Config{ - Hosts: []*config.Host{ - { - Name: "host1", - Interfaces: []*config.Interface{ - { - LogicalName: "eth0", - MACAddress: "00:11:22:33:44:55", - }, - }, - }, - { - Name: "host2", - Interfaces: []*config.Interface{ - { - LogicalName: "eth0", - MACAddress: "00:11:22:33:44:56", - }, - }, - }, - }, - }, - localInterfaces: map[string]string{ - "00:10:20:30:40:50": "eth0", - }, - expectedErr: "identifying host: none of the preconfigured hosts match local NICs", - }, - { - name: "configurator fails due to reading from non-existing config dir", - conf: &config.Config{ - SourceDir: "some-non-existing-dir-123", - Hosts: []*config.Host{ - { - Name: "host1", - Interfaces: []*config.Interface{ - { - LogicalName: "eth0", - MACAddress: "00:11:22:33:44:55", - }, - }, - }, - }, - }, - localInterfaces: map[string]string{ - "00:11:22:33:44:55": "eth0", - }, - expectedErr: "copying files: open some-non-existing-dir-123/host1: no such file or directory", - }, - { - name: "configurator fails due to parsing invalid config file", - conf: &config.Config{ - SourceDir: "testdata", - Hosts: []*config.Host{ - { - Name: "host2", - Interfaces: []*config.Interface{ - { - LogicalName: "eth0", - MACAddress: "00:11:22:33:44:57", - }, - }, - }, - }, - }, - localInterfaces: map[string]string{ - "00:11:22:33:44:57": "eth0", - }, - expectedErr: "copying files: loading file testdata/host2/invalid.nmconnection: key-value delimiter not found: -[connection]\n", - }, - { - name: "configurator fails due to storing to non-existing destination dir", - conf: &config.Config{ - SourceDir: "testdata", - DestinationDir: "some-non-existing-dir-123", - Hosts: []*config.Host{ - { - Name: "host1", - Interfaces: []*config.Interface{ - { - LogicalName: "eth0", - MACAddress: "00:11:22:33:44:57", - }, - }, - }, - }, - }, - localInterfaces: map[string]string{ - "00:11:22:33:44:57": "eth0", - }, - expectedErr: "copying files: storing file some-non-existing-dir-123/eth0.nmconnection: open some-non-existing-dir-123/eth0.nmconnection: no such file or directory", - }, - { - name: "configurator executed successfully", - conf: &config.Config{ - SourceDir: "testdata", - DestinationDir: destDir, - Hosts: []*config.Host{ - { - Name: "host1", - Interfaces: []*config.Interface{ - { - LogicalName: "eth0", - MACAddress: "00:11:22:33:44:55", - }, - }, - }, - }, - }, - localInterfaces: map[string]string{ - "00:11:22:33:44:55": "eth1", - }, - expectedErr: "", - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - configurator := New(test.conf, test.localInterfaces) - - err := configurator.Run() - - if test.expectedErr == "" { - assert.Nil(t, err) - } else { - assert.EqualError(t, err, test.expectedErr) - } - }) - } -} diff --git a/pkg/configurator/network.go b/pkg/configurator/network.go deleted file mode 100644 index 82f9f2b..0000000 --- a/pkg/configurator/network.go +++ /dev/null @@ -1,33 +0,0 @@ -package configurator - -import ( - "net" - "strings" -) - -// NetworkInterfaces maps system network interfaces. -// -// Key is MAC Address. -// Value is Name. -type NetworkInterfaces map[string]string - -func GetNetworkInterfaces() (NetworkInterfaces, error) { - interfaces, err := net.Interfaces() - if err != nil { - return nil, err - } - - interfaceAddresses := map[string]string{} - - for _, i := range interfaces { - if i.HardwareAddr == nil { - // omit loopback / virtual interfaces - continue - } - - address := strings.ToLower(i.HardwareAddr.String()) - interfaceAddresses[address] = i.Name - } - - return interfaceAddresses, nil -} diff --git a/pkg/configurator/testdata/host1/eth0.nmconnection b/pkg/configurator/testdata/host1/eth0.nmconnection deleted file mode 100644 index 71c6723..0000000 --- a/pkg/configurator/testdata/host1/eth0.nmconnection +++ /dev/null @@ -1,23 +0,0 @@ -[connection] -id=eth0 -uuid=4fd00f34-9191-481c-b931-caa24dae871a -type=ethernet -interface-name=eth0 - -[ethernet] - -[ipv4] -address1=192.168.123.1/24 -dns=192.168.123.100 -dns-priority=40 -method=manual -route1=0.0.0.0/0,192.168.123.1 -route1_options=table=254 - -[ipv6] -addr-gen-mode=eui64 -dhcp-duid=ll -dhcp-iaid=mac -method=disabled - -[proxy] diff --git a/pkg/configurator/testdata/host2/invalid.nmconnection b/pkg/configurator/testdata/host2/invalid.nmconnection deleted file mode 100644 index 4bcd520..0000000 --- a/pkg/configurator/testdata/host2/invalid.nmconnection +++ /dev/null @@ -1,6 +0,0 @@ --[connection] -id=eth0 -uuid=d4c69e0e-f9fc-441a-b586-3cfdfffdd70a -type=ethernet -interface-name=eth0 - diff --git a/testdata/host_config.yaml b/testdata/host_config.yaml deleted file mode 100644 index 8873969..0000000 --- a/testdata/host_config.yaml +++ /dev/null @@ -1,11 +0,0 @@ -host_config: - - hostname: node1.example.com - interfaces: - - logical_name: eth0 - mac_address: 00:11:22:33:44:55 - - logical_name: eth0.101 - mac_address: 00:11:22:33:44:56 - - logical_name: eth1 - mac_address: 00:11:22:33:44:57 - - logical_name: bond0 - mac_address: 00:11:22:33:44:58 diff --git a/testdata/node1.example.com/bond0.nmconnection b/testdata/node1.example.com/bond0.nmconnection deleted file mode 100644 index 7065dba..0000000 --- a/testdata/node1.example.com/bond0.nmconnection +++ /dev/null @@ -1,18 +0,0 @@ -[connection] -autoconnect = true -autoconnect-slaves = 1 -id = bond0 -interface-name = bond0 -type = bond -uuid = 925b4a95-2de0-5b2d-bcf5-8b684a7e9cb4 - -[bond] -miimon = 140 -mode = balance-rr - -[ipv4] -address0 = 192.0.2.0/24 -method = manual - -[ipv6] -method = disabled diff --git a/testdata/node1.example.com/eth0.101.nmconnection b/testdata/node1.example.com/eth0.101.nmconnection deleted file mode 100644 index cf6042d..0000000 --- a/testdata/node1.example.com/eth0.101.nmconnection +++ /dev/null @@ -1,23 +0,0 @@ -[connection] -id = eth0.101 -uuid = ad451df9-e022-4ce4-9ba1-4bc691c9abc1 -type = ethernet -interface-name = eth0.101 - -[ethernet] - -[ipv4] -address1 = 192.168.123.3/24 -dns = 192.168.123.100 -dns-priority = 40 -method = manual -route1 = 0.0.0.0/0,192.168.123.3 -route1_options = table=254 - -[ipv6] -addr-gen-mode = eui64 -dhcp-duid = ll -dhcp-iaid = mac -method = disabled - -[proxy] diff --git a/testdata/node1.example.com/eth0.nmconnection b/testdata/node1.example.com/eth0.nmconnection deleted file mode 100644 index 3a7a871..0000000 --- a/testdata/node1.example.com/eth0.nmconnection +++ /dev/null @@ -1,23 +0,0 @@ -[connection] -id = eth0 -uuid = 4fd00f34-9191-481c-b931-caa24dae871a -type = ethernet -interface-name = eth0 - -[ethernet] - -[ipv4] -address1 = 192.168.123.1/24 -dns = 192.168.123.100 -dns-priority = 40 -method = manual -route1 = 0.0.0.0/0,192.168.123.1 -route1_options = table=254 - -[ipv6] -addr-gen-mode = eui64 -dhcp-duid = ll -dhcp-iaid = mac -method = disabled - -[proxy] diff --git a/testdata/node1.example.com/eth1.nmconnection b/testdata/node1.example.com/eth1.nmconnection deleted file mode 100644 index 9669f87..0000000 --- a/testdata/node1.example.com/eth1.nmconnection +++ /dev/null @@ -1,23 +0,0 @@ -[connection] -id = eth1 -uuid = 4fd00f34-9191-481c-b931-caa24dae871a -type = ethernet -interface-name = eth1 - -[ethernet] - -[ipv4] -address1 = 192.168.123.2/24 -dns = 192.168.123.100 -dns-priority = 40 -method = manual -route1 = 0.0.0.0/0,192.168.123.2 -route1_options = table=254 - -[ipv6] -addr-gen-mode = eui64 -dhcp-duid = ll -dhcp-iaid = mac -method = disabled - -[proxy] diff --git a/testdata/node2.example.com/eth0.nmconnection b/testdata/node2.example.com/eth0.nmconnection deleted file mode 100644 index f1de39a..0000000 --- a/testdata/node2.example.com/eth0.nmconnection +++ /dev/null @@ -1,23 +0,0 @@ -[connection] -id = eth0 -uuid = 3cfe4645-8617-4d7f-95b4-c60decc02a4d -type = ethernet -interface-name = eth0 - -[ethernet] - -[ipv4] -address1 = 192.168.123.1/24 -dns = 192.168.123.100 -dns-priority = 40 -method = manual -route1 = 0.0.0.0/0,192.168.123.1 -route1_options = table=254 - -[ipv6] -addr-gen-mode = eui64 -dhcp-duid = ll -dhcp-iaid = mac -method = disabled - -[proxy]