diff --git a/cmd/dhcp4/dhcp4.go b/cmd/dhcp4/dhcp4.go index 22e4336..b436bab 100644 --- a/cmd/dhcp4/dhcp4.go +++ b/cmd/dhcp4/dhcp4.go @@ -32,6 +32,8 @@ func logic() error { c := dhcp4.Client{ Interface: iface, } + usr2 := make(chan os.Signal, 1) + signal.Notify(usr2, syscall.SIGUSR2) for c.ObtainOrRenew() { if err := c.Err(); err != nil { log.Printf("Temporary error: %v", err) @@ -48,7 +50,15 @@ func logic() error { if err := notify.Process("/user/netconfi", syscall.SIGUSR1); err != nil { log.Printf("notifying netconfig: %v", err) } - time.Sleep(time.Until(c.Config().RenewAfter)) + select { + case <-time.After(time.Until(c.Config().RenewAfter)): + // fallthrough and renew the DHCP lease + case <-usr2: + if err := c.Release(); err != nil { + return err + } + os.Exit(125) // quit supervision by gokrazy + } } return c.Err() // permanent error } diff --git a/internal/dhcp4/dhcp4.go b/internal/dhcp4/dhcp4.go index a378241..40ce67f 100644 --- a/internal/dhcp4/dhcp4.go +++ b/internal/dhcp4/dhcp4.go @@ -36,6 +36,9 @@ type Client struct { cfg Config timeNow func() time.Time randRead func([]byte) (int, error) + + // last DHCPACK packet for renewal/release + ack dhcp4.Packet } // ObtainOrRenew returns false when encountering a permanent error. @@ -87,6 +90,7 @@ func (c *Client) ObtainOrRenew() bool { c.err = fmt.Errorf("received DHCPNAK") return true // temporary error } + c.ack = ack opts := ack.ParseOptions() // DHCPACK (described in RFC2131 4.3.1) @@ -131,6 +135,12 @@ func (c *Client) ObtainOrRenew() bool { return true } +func (c *Client) Release() error { + err := c.dhcp.Release(c.ack) + c.ack = nil + return err +} + func (c *Client) Err() error { return c.err }