feat(network): Add support for hwaddress
Currently only supports the ether mode of hwaddress. No immediate plans to support ax25, ARCnet, or netrom.
This commit is contained in:
parent
16d7e8af48
commit
033c8d352f
@ -48,6 +48,10 @@ func (i *logicalInterface) Network() string {
|
|||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i *logicalInterface) Link() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
type physicalInterface struct {
|
type physicalInterface struct {
|
||||||
logicalInterface
|
logicalInterface
|
||||||
}
|
}
|
||||||
@ -60,10 +64,6 @@ func (p *physicalInterface) Netdev() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *physicalInterface) Link() string {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
type bondInterface struct {
|
type bondInterface struct {
|
||||||
logicalInterface
|
logicalInterface
|
||||||
slaves []string
|
slaves []string
|
||||||
@ -77,10 +77,6 @@ func (b *bondInterface) Netdev() string {
|
|||||||
return fmt.Sprintf("[NetDev]\nKind=bond\nName=%s\n", b.name)
|
return fmt.Sprintf("[NetDev]\nKind=bond\nName=%s\n", b.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *bondInterface) Link() string {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
type vlanInterface struct {
|
type vlanInterface struct {
|
||||||
logicalInterface
|
logicalInterface
|
||||||
id int
|
id int
|
||||||
@ -92,11 +88,19 @@ func (v *vlanInterface) Name() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v *vlanInterface) Netdev() string {
|
func (v *vlanInterface) Netdev() string {
|
||||||
return fmt.Sprintf("[NetDev]\nKind=vlan\nName=%s\n\n[VLAN]\nId=%d\n", v.name, v.id)
|
config := fmt.Sprintf("[NetDev]\nKind=vlan\nName=%s\n", v.name)
|
||||||
}
|
switch c := v.config.(type) {
|
||||||
|
case configMethodStatic:
|
||||||
func (v *vlanInterface) Link() string {
|
if c.hwaddress != nil {
|
||||||
return ""
|
config += fmt.Sprintf("MACAddress=%s\n", c.hwaddress)
|
||||||
|
}
|
||||||
|
case configMethodDHCP:
|
||||||
|
if c.hwaddress != nil {
|
||||||
|
config += fmt.Sprintf("MACAddress=%s\n", c.hwaddress)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
config += fmt.Sprintf("\n[VLAN]\nId=%d\n", v.id)
|
||||||
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildInterfaces(stanzas []*stanzaInterface) []InterfaceGenerator {
|
func buildInterfaces(stanzas []*stanzaInterface) []InterfaceGenerator {
|
||||||
|
@ -143,16 +143,26 @@ func TestVLANInterfaceName(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestVLANInterfaceNetdev(t *testing.T) {
|
func TestVLANInterfaceNetdev(t *testing.T) {
|
||||||
v := vlanInterface{logicalInterface{name: "testname"}, 1, ""}
|
for _, tt := range []struct {
|
||||||
netdev := `[NetDev]
|
i vlanInterface
|
||||||
Kind=vlan
|
l string
|
||||||
Name=testname
|
}{
|
||||||
|
{
|
||||||
[VLAN]
|
vlanInterface{logicalInterface{name: "testname"}, 1, ""},
|
||||||
Id=1
|
"[NetDev]\nKind=vlan\nName=testname\n\n[VLAN]\nId=1\n",
|
||||||
`
|
},
|
||||||
if v.Netdev() != netdev {
|
{
|
||||||
t.FailNow()
|
vlanInterface{logicalInterface{name: "testname", config: configMethodStatic{hwaddress: net.HardwareAddr([]byte{0, 1, 2, 3, 4, 5})}}, 1, ""},
|
||||||
|
"[NetDev]\nKind=vlan\nName=testname\nMACAddress=00:01:02:03:04:05\n\n[VLAN]\nId=1\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
vlanInterface{logicalInterface{name: "testname", config: configMethodDHCP{hwaddress: net.HardwareAddr([]byte{0, 1, 2, 3, 4, 5})}}, 1, ""},
|
||||||
|
"[NetDev]\nKind=vlan\nName=testname\nMACAddress=00:01:02:03:04:05\n\n[VLAN]\nId=1\n",
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
if tt.i.Netdev() != tt.l {
|
||||||
|
t.Fatalf("bad netdev config (%q): got %q, want %q", tt.i, tt.i.Netdev(), tt.l)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,13 +40,16 @@ type configMethodStatic struct {
|
|||||||
address net.IPNet
|
address net.IPNet
|
||||||
nameservers []net.IP
|
nameservers []net.IP
|
||||||
routes []route
|
routes []route
|
||||||
|
hwaddress net.HardwareAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
type configMethodLoopback struct{}
|
type configMethodLoopback struct{}
|
||||||
|
|
||||||
type configMethodManual struct{}
|
type configMethodManual struct{}
|
||||||
|
|
||||||
type configMethodDHCP struct{}
|
type configMethodDHCP struct {
|
||||||
|
hwaddress net.HardwareAddr
|
||||||
|
}
|
||||||
|
|
||||||
func parseStanzas(lines []string) (stanzas []stanza, err error) {
|
func parseStanzas(lines []string) (stanzas []stanza, err error) {
|
||||||
rawStanzas, err := splitStanzas(lines)
|
rawStanzas, err := splitStanzas(lines)
|
||||||
@ -217,6 +220,11 @@ func parseInterfaceStanza(attributes []string, options []string) (*stanzaInterfa
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if hwaddress, err := parseHwaddress(optionMap, iface); err == nil {
|
||||||
|
config.hwaddress = hwaddress
|
||||||
|
} else {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
for _, nameserver := range optionMap["dns-nameservers"] {
|
for _, nameserver := range optionMap["dns-nameservers"] {
|
||||||
config.nameservers = append(config.nameservers, net.ParseIP(nameserver))
|
config.nameservers = append(config.nameservers, net.ParseIP(nameserver))
|
||||||
}
|
}
|
||||||
@ -245,7 +253,13 @@ func parseInterfaceStanza(attributes []string, options []string) (*stanzaInterfa
|
|||||||
case "manual":
|
case "manual":
|
||||||
conf = configMethodManual{}
|
conf = configMethodManual{}
|
||||||
case "dhcp":
|
case "dhcp":
|
||||||
conf = configMethodDHCP{}
|
config := configMethodDHCP{}
|
||||||
|
if hwaddress, err := parseHwaddress(optionMap, iface); err == nil {
|
||||||
|
config.hwaddress = hwaddress
|
||||||
|
} else {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
conf = config
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("invalid config method %q", confMethod)
|
return nil, fmt.Errorf("invalid config method %q", confMethod)
|
||||||
}
|
}
|
||||||
@ -265,6 +279,19 @@ func parseInterfaceStanza(attributes []string, options []string) (*stanzaInterfa
|
|||||||
return parsePhysicalStanza(iface, conf, attributes, optionMap)
|
return parsePhysicalStanza(iface, conf, attributes, optionMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseHwaddress(options map[string][]string, iface string) (net.HardwareAddr, error) {
|
||||||
|
if hwaddress, ok := options["hwaddress"]; ok && len(hwaddress) == 2 {
|
||||||
|
switch hwaddress[0] {
|
||||||
|
case "ether":
|
||||||
|
if address, err := net.ParseMAC(hwaddress[1]); err == nil {
|
||||||
|
return address, nil
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("malformed hwaddress option for %q", iface)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
func parseBondStanza(iface string, conf configMethod, attributes []string, options map[string][]string) (*stanzaInterface, error) {
|
func parseBondStanza(iface string, conf configMethod, attributes []string, options map[string][]string) (*stanzaInterface, error) {
|
||||||
options["slaves"] = options["bond-slaves"]
|
options["slaves"] = options["bond-slaves"]
|
||||||
return &stanzaInterface{name: iface, kind: interfaceBond, configMethod: conf, options: options}, nil
|
return &stanzaInterface{name: iface, kind: interfaceBond, configMethod: conf, options: options}, nil
|
||||||
|
@ -42,6 +42,8 @@ func TestBadParseInterfaceStanza(t *testing.T) {
|
|||||||
{[]string{"eth", "inet", "static"}, []string{"netmask 255.255.255.0"}, "malformed static network config"},
|
{[]string{"eth", "inet", "static"}, []string{"netmask 255.255.255.0"}, "malformed static network config"},
|
||||||
{[]string{"eth", "inet", "static"}, []string{"address invalid", "netmask 255.255.255.0"}, "malformed static network config"},
|
{[]string{"eth", "inet", "static"}, []string{"address invalid", "netmask 255.255.255.0"}, "malformed static network config"},
|
||||||
{[]string{"eth", "inet", "static"}, []string{"address 192.168.1.100", "netmask invalid"}, "malformed static network config"},
|
{[]string{"eth", "inet", "static"}, []string{"address 192.168.1.100", "netmask invalid"}, "malformed static network config"},
|
||||||
|
{[]string{"eth", "inet", "static"}, []string{"address 192.168.1.100", "netmask 255.255.255.0", "hwaddress ether NotAnAddress"}, "malformed hwaddress option"},
|
||||||
|
{[]string{"eth", "inet", "dhcp"}, []string{"hwaddress ether NotAnAddress"}, "malformed hwaddress option"},
|
||||||
} {
|
} {
|
||||||
_, err := parseInterfaceStanza(tt.in, tt.opts)
|
_, err := parseInterfaceStanza(tt.in, tt.opts)
|
||||||
if err == nil || !strings.HasPrefix(err.Error(), tt.e) {
|
if err == nil || !strings.HasPrefix(err.Error(), tt.e) {
|
||||||
@ -407,7 +409,46 @@ func TestParseInterfaceStanzaOptions(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseInterfaceStazaBond(t *testing.T) {
|
func TestParseInterfaceStanzaHwaddress(t *testing.T) {
|
||||||
|
for _, tt := range []struct {
|
||||||
|
attr []string
|
||||||
|
opt []string
|
||||||
|
hw net.HardwareAddr
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
[]string{"mybond", "inet", "dhcp"},
|
||||||
|
[]string{},
|
||||||
|
nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
[]string{"mybond", "inet", "dhcp"},
|
||||||
|
[]string{"hwaddress ether 00:01:02:03:04:05"},
|
||||||
|
net.HardwareAddr([]byte{0, 1, 2, 3, 4, 5}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
[]string{"mybond", "inet", "static"},
|
||||||
|
[]string{"hwaddress ether 00:01:02:03:04:05", "address 192.168.1.100", "netmask 255.255.255.0"},
|
||||||
|
net.HardwareAddr([]byte{0, 1, 2, 3, 4, 5}),
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
iface, err := parseInterfaceStanza(tt.attr, tt.opt)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error in parseInterfaceStanza (%q, %q): %q", tt.attr, tt.opt, err)
|
||||||
|
}
|
||||||
|
switch c := iface.configMethod.(type) {
|
||||||
|
case configMethodStatic:
|
||||||
|
if !reflect.DeepEqual(c.hwaddress, tt.hw) {
|
||||||
|
t.Fatalf("bad hwaddress (%q, %q): got %q, want %q", tt.attr, tt.opt, c.hwaddress, tt.hw)
|
||||||
|
}
|
||||||
|
case configMethodDHCP:
|
||||||
|
if !reflect.DeepEqual(c.hwaddress, tt.hw) {
|
||||||
|
t.Fatalf("bad hwaddress (%q, %q): got %q, want %q", tt.attr, tt.opt, c.hwaddress, tt.hw)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseInterfaceStanzaBond(t *testing.T) {
|
||||||
iface, err := parseInterfaceStanza([]string{"mybond", "inet", "manual"}, []string{"bond-slaves eth"})
|
iface, err := parseInterfaceStanza([]string{"mybond", "inet", "manual"}, []string{"bond-slaves eth"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
@ -417,7 +458,7 @@ func TestParseInterfaceStazaBond(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseInterfaceStazaVLANName(t *testing.T) {
|
func TestParseInterfaceStanzaVLANName(t *testing.T) {
|
||||||
iface, err := parseInterfaceStanza([]string{"eth0.1", "inet", "manual"}, nil)
|
iface, err := parseInterfaceStanza([]string{"eth0.1", "inet", "manual"}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
@ -427,7 +468,7 @@ func TestParseInterfaceStazaVLANName(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseInterfaceStazaVLANOption(t *testing.T) {
|
func TestParseInterfaceStanzaVLANOption(t *testing.T) {
|
||||||
iface, err := parseInterfaceStanza([]string{"vlan1", "inet", "manual"}, []string{"vlan_raw_device eth"})
|
iface, err := parseInterfaceStanza([]string{"vlan1", "inet", "manual"}, []string{"vlan_raw_device eth"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
|
Loading…
Reference in New Issue
Block a user