dhcp4: use the configured (not the current) MAC address
This fixes a race where dhcp4 started before netconfigd had a chance to change the hardware address on the uplink0 interface. fiber7’s port security feature may result in an about hour-long internet outage without this commit.
This commit is contained in:
parent
66942bd4f7
commit
3dad1e9a23
@ -33,6 +33,7 @@ import (
|
||||
"github.com/google/renameio"
|
||||
"github.com/jpillora/backoff"
|
||||
"github.com/rtr7/router7/internal/dhcp4"
|
||||
"github.com/rtr7/router7/internal/netconfig"
|
||||
"github.com/rtr7/router7/internal/notify"
|
||||
"github.com/rtr7/router7/internal/teelogger"
|
||||
)
|
||||
@ -48,6 +49,20 @@ func logic() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hwaddr := iface.HardwareAddr
|
||||
// The interface may not have been configured by netconfigd yet and might
|
||||
// still use the old hardware address. We overwrite it with the address that
|
||||
// netconfigd is going to use to fix this issue without additional
|
||||
// synchronization.
|
||||
details, err := netconfig.Interface("/perm", "uplink0")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if spoof := details.SpoofHardwareAddr; spoof != "" {
|
||||
if addr, err := net.ParseMAC(spoof); err == nil {
|
||||
hwaddr = addr
|
||||
}
|
||||
}
|
||||
const ackFn = "/perm/dhcp4/wire/ack"
|
||||
var ack *layers.DHCPv4
|
||||
ackB, err := ioutil.ReadFile(ackFn)
|
||||
@ -61,6 +76,7 @@ func logic() error {
|
||||
}
|
||||
c := dhcp4.Client{
|
||||
Interface: iface,
|
||||
HWAddr: hwaddr,
|
||||
Ack: ack,
|
||||
}
|
||||
usr2 := make(chan os.Signal, 1)
|
||||
|
@ -40,6 +40,7 @@ type Config struct {
|
||||
|
||||
type Client struct {
|
||||
Interface *net.Interface // e.g. net.InterfaceByName("eth0")
|
||||
HWAddr net.HardwareAddr
|
||||
|
||||
err error
|
||||
once sync.Once
|
||||
@ -102,6 +103,9 @@ func (c *Client) ObtainOrRenew() bool {
|
||||
onceErr = fmt.Errorf("Interface is nil")
|
||||
return
|
||||
}
|
||||
if c.hardwareAddr == nil && c.HWAddr != nil {
|
||||
c.hardwareAddr = c.HWAddr
|
||||
}
|
||||
if c.hardwareAddr == nil {
|
||||
c.hardwareAddr = c.Interface.HardwareAddr
|
||||
}
|
||||
|
@ -184,26 +184,36 @@ type InterfaceConfig struct {
|
||||
Interfaces []InterfaceDetails `json:"interfaces"`
|
||||
}
|
||||
|
||||
// LinkAddress returns the IP address configured for the interface ifname in
|
||||
// Interface returns the InterfaceDetails configured for interface ifname in
|
||||
// interfaces.json.
|
||||
func LinkAddress(dir, ifname string) (net.IP, error) {
|
||||
func Interface(dir, ifname string) (InterfaceDetails, error) {
|
||||
fn := filepath.Join(dir, "interfaces.json")
|
||||
b, err := ioutil.ReadFile(fn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return InterfaceDetails{}, err
|
||||
}
|
||||
var cfg InterfaceConfig
|
||||
if err := json.Unmarshal(b, &cfg); err != nil {
|
||||
return nil, err
|
||||
return InterfaceDetails{}, err
|
||||
}
|
||||
for _, details := range cfg.Interfaces {
|
||||
if details.Name != ifname {
|
||||
continue
|
||||
}
|
||||
ip, _, err := net.ParseCIDR(details.Addr)
|
||||
return ip, err
|
||||
return details, nil
|
||||
}
|
||||
return nil, fmt.Errorf("%s does not configure interface %q", fn, ifname)
|
||||
return InterfaceDetails{}, fmt.Errorf("%s does not configure interface %q", fn, ifname)
|
||||
}
|
||||
|
||||
// LinkAddress returns the IP address configured for the interface ifname in
|
||||
// interfaces.json.
|
||||
func LinkAddress(dir, ifname string) (net.IP, error) {
|
||||
iface, err := Interface(dir, ifname)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ip, _, err := net.ParseCIDR(iface.Addr)
|
||||
return ip, err
|
||||
}
|
||||
|
||||
func applyInterfaces(dir, root string) error {
|
||||
|
Loading…
x
Reference in New Issue
Block a user