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/google/renameio"
|
||||||
"github.com/jpillora/backoff"
|
"github.com/jpillora/backoff"
|
||||||
"github.com/rtr7/router7/internal/dhcp4"
|
"github.com/rtr7/router7/internal/dhcp4"
|
||||||
|
"github.com/rtr7/router7/internal/netconfig"
|
||||||
"github.com/rtr7/router7/internal/notify"
|
"github.com/rtr7/router7/internal/notify"
|
||||||
"github.com/rtr7/router7/internal/teelogger"
|
"github.com/rtr7/router7/internal/teelogger"
|
||||||
)
|
)
|
||||||
@ -48,6 +49,20 @@ func logic() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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"
|
const ackFn = "/perm/dhcp4/wire/ack"
|
||||||
var ack *layers.DHCPv4
|
var ack *layers.DHCPv4
|
||||||
ackB, err := ioutil.ReadFile(ackFn)
|
ackB, err := ioutil.ReadFile(ackFn)
|
||||||
@ -61,6 +76,7 @@ func logic() error {
|
|||||||
}
|
}
|
||||||
c := dhcp4.Client{
|
c := dhcp4.Client{
|
||||||
Interface: iface,
|
Interface: iface,
|
||||||
|
HWAddr: hwaddr,
|
||||||
Ack: ack,
|
Ack: ack,
|
||||||
}
|
}
|
||||||
usr2 := make(chan os.Signal, 1)
|
usr2 := make(chan os.Signal, 1)
|
||||||
|
@ -40,6 +40,7 @@ type Config struct {
|
|||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
Interface *net.Interface // e.g. net.InterfaceByName("eth0")
|
Interface *net.Interface // e.g. net.InterfaceByName("eth0")
|
||||||
|
HWAddr net.HardwareAddr
|
||||||
|
|
||||||
err error
|
err error
|
||||||
once sync.Once
|
once sync.Once
|
||||||
@ -102,6 +103,9 @@ func (c *Client) ObtainOrRenew() bool {
|
|||||||
onceErr = fmt.Errorf("Interface is nil")
|
onceErr = fmt.Errorf("Interface is nil")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if c.hardwareAddr == nil && c.HWAddr != nil {
|
||||||
|
c.hardwareAddr = c.HWAddr
|
||||||
|
}
|
||||||
if c.hardwareAddr == nil {
|
if c.hardwareAddr == nil {
|
||||||
c.hardwareAddr = c.Interface.HardwareAddr
|
c.hardwareAddr = c.Interface.HardwareAddr
|
||||||
}
|
}
|
||||||
|
@ -184,26 +184,36 @@ type InterfaceConfig struct {
|
|||||||
Interfaces []InterfaceDetails `json:"interfaces"`
|
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.
|
// interfaces.json.
|
||||||
func LinkAddress(dir, ifname string) (net.IP, error) {
|
func Interface(dir, ifname string) (InterfaceDetails, error) {
|
||||||
fn := filepath.Join(dir, "interfaces.json")
|
fn := filepath.Join(dir, "interfaces.json")
|
||||||
b, err := ioutil.ReadFile(fn)
|
b, err := ioutil.ReadFile(fn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return InterfaceDetails{}, err
|
||||||
}
|
}
|
||||||
var cfg InterfaceConfig
|
var cfg InterfaceConfig
|
||||||
if err := json.Unmarshal(b, &cfg); err != nil {
|
if err := json.Unmarshal(b, &cfg); err != nil {
|
||||||
return nil, err
|
return InterfaceDetails{}, err
|
||||||
}
|
}
|
||||||
for _, details := range cfg.Interfaces {
|
for _, details := range cfg.Interfaces {
|
||||||
if details.Name != ifname {
|
if details.Name != ifname {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
ip, _, err := net.ParseCIDR(details.Addr)
|
return details, nil
|
||||||
return ip, err
|
|
||||||
}
|
}
|
||||||
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 {
|
func applyInterfaces(dir, root string) error {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user