Skip to content

Commit

Permalink
dhcpsvc: imp filing
Browse files Browse the repository at this point in the history
  • Loading branch information
EugeneOne1 committed Sep 22, 2023
1 parent 57c91e1 commit 91a0e45
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 94 deletions.
94 changes: 0 additions & 94 deletions internal/dhcpsvc/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,107 +2,13 @@ package dhcpsvc

import (
"fmt"
"net"
"net/netip"
"sync/atomic"
"time"

"golang.org/x/exp/maps"
"golang.org/x/exp/slices"
)

// iface4 is a DHCP interface for IPv4 address family.
type iface4 struct {
// gateway is the IP address of the network gateway.
gateway netip.Addr

// subnet is the network subnet.
subnet netip.Prefix

// addrSpace is the IPv4 address space allocated for leasing.
addrSpace ipRange

// name is the name of the interface.
name string

// TODO(e.burkov): Add options.

// leaseTTL is the time-to-live of dynamic leases on this interface.
leaseTTL time.Duration
}

// newIface4 creates a new DHCP interface for IPv4 address family with the given
// configuration. It returns an error if the given configuration can't be used.
func newIface4(name string, conf *IPv4Config) (i *iface4, err error) {
if !conf.Enabled {
return nil, nil
}

maskLen, _ := net.IPMask(conf.SubnetMask.AsSlice()).Size()
subnet := netip.PrefixFrom(conf.GatewayIP, maskLen)

switch {
case !subnet.Contains(conf.RangeStart):
return nil, fmt.Errorf("range start %s is not within %s", conf.RangeStart, subnet)
case !subnet.Contains(conf.RangeEnd):
return nil, fmt.Errorf("range end %s is not within %s", conf.RangeEnd, subnet)
}

addrSpace, err := newIPRange(conf.RangeStart, conf.RangeEnd)
if err != nil {
return nil, err
} else if addrSpace.contains(conf.GatewayIP) {
return nil, fmt.Errorf("gateway ip %s in the ip range %s", conf.GatewayIP, addrSpace)
}

return &iface4{
name: name,
gateway: conf.GatewayIP,
subnet: subnet,
addrSpace: addrSpace,
leaseTTL: conf.LeaseDuration,
}, nil
}

// iface6 is a DHCP interface for IPv6 address family.
//
// TODO(e.burkov): Add options.
type iface6 struct {
// rangeStart is the first IP address in the range.
rangeStart netip.Addr

// name is the name of the interface.
name string

// leaseTTL is the time-to-live of dynamic leases on this interface.
leaseTTL time.Duration

// raSLAACOnly defines if DHCP should send ICMPv6.RA packets without MO
// flags.
raSLAACOnly bool

// raAllowSLAAC defines if DHCP should send ICMPv6.RA packets with MO flags.
raAllowSLAAC bool
}

// newIface6 creates a new DHCP interface for IPv6 address family with the given
// configuration.
//
// TODO(e.burkov): Validate properly.
func newIface6(name string, conf *IPv6Config) (i *iface6) {
if !conf.Enabled {
return nil
}

return &iface6{
name: name,
rangeStart: conf.RangeStart,
leaseTTL: conf.LeaseDuration,
raSLAACOnly: conf.RASLAACOnly,
raAllowSLAAC: conf.RAAllowSLAAC,
}
}

// DHCPServer is a DHCP server for both IPv4 and IPv6 address families.
type DHCPServer struct {
// enabled indicates whether the DHCP server is enabled and can provide
Expand Down
55 changes: 55 additions & 0 deletions internal/dhcpsvc/v4.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package dhcpsvc

import (
"fmt"
"net"
"net/netip"
"time"

Expand Down Expand Up @@ -56,3 +58,56 @@ func (conf *IPv4Config) validate() (err error) {
return nil
}
}

// iface4 is a DHCP interface for IPv4 address family.
type iface4 struct {
// gateway is the IP address of the network gateway.
gateway netip.Addr

// subnet is the network subnet.
subnet netip.Prefix

// addrSpace is the IPv4 address space allocated for leasing.
addrSpace ipRange

// name is the name of the interface.
name string

// TODO(e.burkov): Add options.

// leaseTTL is the time-to-live of dynamic leases on this interface.
leaseTTL time.Duration
}

// newIface4 creates a new DHCP interface for IPv4 address family with the given
// configuration. It returns an error if the given configuration can't be used.
func newIface4(name string, conf *IPv4Config) (i *iface4, err error) {
if !conf.Enabled {
return nil, nil
}

maskLen, _ := net.IPMask(conf.SubnetMask.AsSlice()).Size()
subnet := netip.PrefixFrom(conf.GatewayIP, maskLen)

switch {
case !subnet.Contains(conf.RangeStart):
return nil, fmt.Errorf("range start %s is not within %s", conf.RangeStart, subnet)
case !subnet.Contains(conf.RangeEnd):
return nil, fmt.Errorf("range end %s is not within %s", conf.RangeEnd, subnet)
}

addrSpace, err := newIPRange(conf.RangeStart, conf.RangeEnd)
if err != nil {
return nil, err
} else if addrSpace.contains(conf.GatewayIP) {
return nil, fmt.Errorf("gateway ip %s in the ip range %s", conf.GatewayIP, addrSpace)
}

return &iface4{
name: name,
gateway: conf.GatewayIP,
subnet: subnet,
addrSpace: addrSpace,
leaseTTL: conf.LeaseDuration,
}, nil
}
39 changes: 39 additions & 0 deletions internal/dhcpsvc/v6.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,42 @@ func (conf *IPv6Config) validate() (err error) {
return nil
}
}

// iface6 is a DHCP interface for IPv6 address family.
//
// TODO(e.burkov): Add options.
type iface6 struct {
// rangeStart is the first IP address in the range.
rangeStart netip.Addr

// name is the name of the interface.
name string

// leaseTTL is the time-to-live of dynamic leases on this interface.
leaseTTL time.Duration

// raSLAACOnly defines if DHCP should send ICMPv6.RA packets without MO
// flags.
raSLAACOnly bool

// raAllowSLAAC defines if DHCP should send ICMPv6.RA packets with MO flags.
raAllowSLAAC bool
}

// newIface6 creates a new DHCP interface for IPv6 address family with the given
// configuration.
//
// TODO(e.burkov): Validate properly.
func newIface6(name string, conf *IPv6Config) (i *iface6) {
if !conf.Enabled {
return nil
}

return &iface6{
name: name,
rangeStart: conf.RangeStart,
leaseTTL: conf.LeaseDuration,
raSLAACOnly: conf.RASLAACOnly,
raAllowSLAAC: conf.RAAllowSLAAC,
}
}

0 comments on commit 91a0e45

Please sign in to comment.