dhcp4: persist DHCPACK to renew existing lease after reboot
This commit is contained in:
parent
4f4f286a43
commit
8b85084429
@ -5,6 +5,7 @@ package main
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
@ -21,16 +22,22 @@ import (
|
||||
var log = teelogger.NewConsole()
|
||||
|
||||
func logic() error {
|
||||
const configPath = "/perm/dhcp4/wire/lease.json"
|
||||
if err := os.MkdirAll(filepath.Dir(configPath), 0755); err != nil {
|
||||
const leasePath = "/perm/dhcp4/wire/lease.json"
|
||||
if err := os.MkdirAll(filepath.Dir(leasePath), 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
iface, err := net.InterfaceByName("uplink0")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
const ackFn = "/perm/dhcp4/wire/ack"
|
||||
ack, err := ioutil.ReadFile(ackFn)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
log.Printf("Loading previous DHCPACK packet from %s: %v", ackFn, err)
|
||||
}
|
||||
c := dhcp4.Client{
|
||||
Interface: iface,
|
||||
Ack: ack,
|
||||
}
|
||||
usr2 := make(chan os.Signal, 1)
|
||||
signal.Notify(usr2, syscall.SIGUSR2)
|
||||
@ -45,8 +52,11 @@ func logic() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ioutil.WriteFile(configPath, b, 0644); err != nil {
|
||||
return err
|
||||
if err := ioutil.WriteFile(leasePath, b, 0644); err != nil {
|
||||
return fmt.Errorf("persisting lease to %s: %v", leasePath, err)
|
||||
}
|
||||
if err := ioutil.WriteFile(ackFn, c.Ack, 0644); err != nil {
|
||||
return fmt.Errorf("persisting DHCPACK to %s: %v", ackFn, err)
|
||||
}
|
||||
if err := notify.Process("/user/netconfi", syscall.SIGUSR1); err != nil {
|
||||
log.Printf("notifying netconfig: %v", err)
|
||||
|
@ -88,6 +88,7 @@ func TestDHCPv4(t *testing.T) {
|
||||
c := dhcp4.Client{
|
||||
Interface: iface,
|
||||
}
|
||||
// Obtain first, then renew
|
||||
for i := 0; i < 2; i++ {
|
||||
if !c.ObtainOrRenew() {
|
||||
t.Fatal(c.Err())
|
||||
@ -96,6 +97,21 @@ func TestDHCPv4(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Renew once more, but with a new client object (simulating a dhcp4 process
|
||||
// restart).
|
||||
ack := c.Ack
|
||||
c = dhcp4.Client{
|
||||
Interface: iface,
|
||||
Ack: ack,
|
||||
}
|
||||
if !c.ObtainOrRenew() {
|
||||
t.Fatal(c.Err())
|
||||
}
|
||||
if err := c.Err(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cfg := c.Config()
|
||||
t.Logf("cfg = %+v", cfg)
|
||||
if got, want := cfg.Router, "192.168.23.1"; got != want {
|
||||
@ -121,6 +137,9 @@ func TestDHCPv4(t *testing.T) {
|
||||
"DHCPREQUEST(veth0b) 192.168.23.4 02:73:53:00:ca:fe",
|
||||
"DHCPACK(veth0b) 192.168.23.4 02:73:53:00:ca:fe midna",
|
||||
|
||||
"DHCPREQUEST(veth0b) 192.168.23.4 02:73:53:00:ca:fe",
|
||||
"DHCPACK(veth0b) 192.168.23.4 02:73:53:00:ca:fe midna",
|
||||
|
||||
"DHCPRELEASE(veth0b) 192.168.23.4 02:73:53:00:ca:fe",
|
||||
}
|
||||
trimSpace := func(line string) string {
|
||||
|
@ -38,7 +38,7 @@ type Client struct {
|
||||
generateXID func([]byte)
|
||||
|
||||
// last DHCPACK packet for renewal/release
|
||||
ack dhcp4.Packet
|
||||
Ack dhcp4.Packet
|
||||
}
|
||||
|
||||
// ObtainOrRenew returns false when encountering a permanent error.
|
||||
@ -76,7 +76,6 @@ func (c *Client) ObtainOrRenew() bool {
|
||||
c.dhcp = dhcp
|
||||
})
|
||||
c.err = nil // clear previous error
|
||||
// TODO: renew if c.ack != nil, fall back if renewal fails
|
||||
ok, ack, err := c.dhcpRequest()
|
||||
if err != nil {
|
||||
if errno, ok := err.(syscall.Errno); ok && errno == syscall.EAGAIN {
|
||||
@ -90,7 +89,7 @@ func (c *Client) ObtainOrRenew() bool {
|
||||
c.err = fmt.Errorf("received DHCPNAK")
|
||||
return true // temporary error
|
||||
}
|
||||
c.ack = ack
|
||||
c.Ack = ack
|
||||
opts := ack.ParseOptions()
|
||||
|
||||
// DHCPACK (described in RFC2131 4.3.1)
|
||||
@ -136,8 +135,8 @@ func (c *Client) ObtainOrRenew() bool {
|
||||
}
|
||||
|
||||
func (c *Client) Release() error {
|
||||
err := c.dhcp.Release(c.ack)
|
||||
c.ack = nil
|
||||
err := c.dhcp.Release(c.Ack)
|
||||
c.Ack = nil
|
||||
return err
|
||||
}
|
||||
|
||||
@ -173,7 +172,7 @@ func (c *Client) addClientId(p *dhcp4.Packet) {
|
||||
// includes the hostname.
|
||||
func (c *Client) dhcpRequest() (bool, dhcp4.Packet, error) {
|
||||
var last dhcp4.Packet
|
||||
if c.ack == nil {
|
||||
if c.Ack == nil {
|
||||
discoveryPacket := c.dhcp.DiscoverPacket()
|
||||
c.addHostname(&discoveryPacket)
|
||||
c.addClientId(&discoveryPacket)
|
||||
@ -189,7 +188,7 @@ func (c *Client) dhcpRequest() (bool, dhcp4.Packet, error) {
|
||||
}
|
||||
last = offerPacket
|
||||
} else {
|
||||
last = c.ack
|
||||
last = c.Ack
|
||||
}
|
||||
|
||||
requestPacket := c.dhcp.RequestPacket(&last)
|
||||
@ -208,7 +207,7 @@ func (c *Client) dhcpRequest() (bool, dhcp4.Packet, error) {
|
||||
|
||||
acknowledgementOptions := acknowledgement.ParseOptions()
|
||||
if dhcp4.MessageType(acknowledgementOptions[dhcp4.OptionDHCPMessageType][0]) != dhcp4.ACK {
|
||||
c.ack = nil // start over
|
||||
c.Ack = nil // start over
|
||||
return false, acknowledgement, nil
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user