
The dhcp server is systemd-networkd, and the dhcp plugin can request an ip but can not renew it. The systemd-networkd just ignore the renew request. ``` 2024/09/14 21:46:00 no DHCP packet received within 10s 2024/09/14 21:46:00 retrying in 31.529038 seconds 2024/09/14 21:46:42 no DHCP packet received within 10s 2024/09/14 21:46:42 retrying in 63.150490 seconds 2024/09/14 21:47:45 98184616c91f15419f5cacd012697f85afaa2daeb5d3233e28b0ec21589fb45a/iot/eth1: no more tries 2024/09/14 21:47:45 98184616c91f15419f5cacd012697f85afaa2daeb5d3233e28b0ec21589fb45a/iot/eth1: renewal time expired, rebinding 2024/09/14 21:47:45 Link "eth1" down. Attempting to set up 2024/09/14 21:47:45 98184616c91f15419f5cacd012697f85afaa2daeb5d3233e28b0ec21589fb45a/iot/eth1: lease rebound, expiration is 2024-09-14 22:47:45.309270751 +0800 CST m=+11730.048516519 ``` Follow the https://datatracker.ietf.org/doc/html/rfc2131#section-4.3.6, following options must not be sent in renew - Requested IP Address - Server Identifier Since the upstream code has been inactive for 6 years, we should switch to another dhcpv4 library. The new selected one is https://github.com/insomniacslk/dhcp. Signed-off-by: Songmin Li <lisongmin@protonmail.com>
177 lines
4.4 KiB
Go
177 lines
4.4 KiB
Go
package dhcpv4
|
|
|
|
import (
|
|
"net"
|
|
"time"
|
|
|
|
"github.com/insomniacslk/dhcp/iana"
|
|
"github.com/insomniacslk/dhcp/rfc1035label"
|
|
)
|
|
|
|
// WithTransactionID sets the Transaction ID for the DHCPv4 packet
|
|
func WithTransactionID(xid TransactionID) Modifier {
|
|
return func(d *DHCPv4) {
|
|
d.TransactionID = xid
|
|
}
|
|
}
|
|
|
|
// WithClientIP sets the Client IP for a DHCPv4 packet.
|
|
func WithClientIP(ip net.IP) Modifier {
|
|
return func(d *DHCPv4) {
|
|
d.ClientIPAddr = ip
|
|
}
|
|
}
|
|
|
|
// WithYourIP sets the Your IP for a DHCPv4 packet.
|
|
func WithYourIP(ip net.IP) Modifier {
|
|
return func(d *DHCPv4) {
|
|
d.YourIPAddr = ip
|
|
}
|
|
}
|
|
|
|
// WithServerIP sets the Server IP for a DHCPv4 packet.
|
|
func WithServerIP(ip net.IP) Modifier {
|
|
return func(d *DHCPv4) {
|
|
d.ServerIPAddr = ip
|
|
}
|
|
}
|
|
|
|
// WithGatewayIP sets the Gateway IP for the DHCPv4 packet.
|
|
func WithGatewayIP(ip net.IP) Modifier {
|
|
return func(d *DHCPv4) {
|
|
d.GatewayIPAddr = ip
|
|
}
|
|
}
|
|
|
|
// WithOptionCopied copies the value of option opt from request.
|
|
func WithOptionCopied(request *DHCPv4, opt OptionCode) Modifier {
|
|
return func(d *DHCPv4) {
|
|
if val := request.Options.Get(opt); val != nil {
|
|
d.UpdateOption(OptGeneric(opt, val))
|
|
}
|
|
}
|
|
}
|
|
|
|
// WithReply fills in opcode, hwtype, xid, clienthwaddr, and flags from the given packet.
|
|
func WithReply(request *DHCPv4) Modifier {
|
|
return func(d *DHCPv4) {
|
|
if request.OpCode == OpcodeBootRequest {
|
|
d.OpCode = OpcodeBootReply
|
|
} else {
|
|
d.OpCode = OpcodeBootRequest
|
|
}
|
|
d.HWType = request.HWType
|
|
d.TransactionID = request.TransactionID
|
|
d.ClientHWAddr = request.ClientHWAddr
|
|
d.Flags = request.Flags
|
|
}
|
|
}
|
|
|
|
// WithHWType sets the Hardware Type for a DHCPv4 packet.
|
|
func WithHWType(hwt iana.HWType) Modifier {
|
|
return func(d *DHCPv4) {
|
|
d.HWType = hwt
|
|
}
|
|
}
|
|
|
|
// WithBroadcast sets the packet to be broadcast or unicast
|
|
func WithBroadcast(broadcast bool) Modifier {
|
|
return func(d *DHCPv4) {
|
|
if broadcast {
|
|
d.SetBroadcast()
|
|
} else {
|
|
d.SetUnicast()
|
|
}
|
|
}
|
|
}
|
|
|
|
// WithHwAddr sets the hardware address for a packet
|
|
func WithHwAddr(hwaddr net.HardwareAddr) Modifier {
|
|
return func(d *DHCPv4) {
|
|
d.ClientHWAddr = hwaddr
|
|
}
|
|
}
|
|
|
|
// WithOption appends a DHCPv4 option provided by the user
|
|
func WithOption(opt Option) Modifier {
|
|
return func(d *DHCPv4) {
|
|
d.UpdateOption(opt)
|
|
}
|
|
}
|
|
|
|
// WithoutOption removes the DHCPv4 option with the given code
|
|
func WithoutOption(code OptionCode) Modifier {
|
|
return func(d *DHCPv4) {
|
|
d.DeleteOption(code)
|
|
}
|
|
}
|
|
|
|
// WithUserClass adds a user class option to the packet.
|
|
// The rfc parameter allows you to specify if the userclass should be
|
|
// rfc compliant or not. More details in issue #113
|
|
func WithUserClass(uc string, rfc bool) Modifier {
|
|
// TODO let the user specify multiple user classes
|
|
return func(d *DHCPv4) {
|
|
if rfc {
|
|
d.UpdateOption(OptRFC3004UserClass([]string{uc}))
|
|
} else {
|
|
d.UpdateOption(OptUserClass(uc))
|
|
}
|
|
}
|
|
}
|
|
|
|
// WithNetboot adds bootfile URL and bootfile param options to a DHCPv4 packet.
|
|
func WithNetboot(d *DHCPv4) {
|
|
WithRequestedOptions(OptionTFTPServerName, OptionBootfileName)(d)
|
|
}
|
|
|
|
// WithMessageType adds the DHCPv4 message type m to a packet.
|
|
func WithMessageType(m MessageType) Modifier {
|
|
return WithOption(OptMessageType(m))
|
|
}
|
|
|
|
// WithRequestedOptions adds requested options to the packet.
|
|
func WithRequestedOptions(optionCodes ...OptionCode) Modifier {
|
|
return func(d *DHCPv4) {
|
|
cl := d.ParameterRequestList()
|
|
cl.Add(optionCodes...)
|
|
d.UpdateOption(OptParameterRequestList(cl...))
|
|
}
|
|
}
|
|
|
|
// WithRelay adds parameters required for DHCPv4 to be relayed by the relay
|
|
// server with given ip
|
|
func WithRelay(ip net.IP) Modifier {
|
|
return func(d *DHCPv4) {
|
|
d.SetUnicast()
|
|
d.GatewayIPAddr = ip
|
|
d.HopCount++
|
|
}
|
|
}
|
|
|
|
// WithNetmask adds or updates an OptSubnetMask
|
|
func WithNetmask(mask net.IPMask) Modifier {
|
|
return WithOption(OptSubnetMask(mask))
|
|
}
|
|
|
|
// WithLeaseTime adds or updates an OptIPAddressLeaseTime
|
|
func WithLeaseTime(leaseTime uint32) Modifier {
|
|
return WithOption(OptIPAddressLeaseTime(time.Duration(leaseTime) * time.Second))
|
|
}
|
|
|
|
// WithIPv6OnlyPreferred adds or updates an OptIPv6OnlyPreferred
|
|
func WithIPv6OnlyPreferred(v6OnlyWait uint32) Modifier {
|
|
return WithOption(OptIPv6OnlyPreferred(time.Duration(v6OnlyWait) * time.Second))
|
|
}
|
|
|
|
// WithDomainSearchList adds or updates an OptionDomainSearch
|
|
func WithDomainSearchList(searchList ...string) Modifier {
|
|
return WithOption(OptDomainSearch(&rfc1035label.Labels{
|
|
Labels: searchList,
|
|
}))
|
|
}
|
|
|
|
func WithGeneric(code OptionCode, value []byte) Modifier {
|
|
return WithOption(OptGeneric(code, value))
|
|
}
|