65 lines
1.4 KiB
Go
65 lines
1.4 KiB
Go
package iptools
|
|
|
|
import (
|
|
"fmt"
|
|
"net/netip"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
DefaultMaskBits = 24
|
|
)
|
|
|
|
type Range struct {
|
|
Start netip.Addr `yaml:"start" json:"start"`
|
|
End netip.Addr `yaml:"end" json:"end"`
|
|
Network netip.Prefix `yaml:"network" json:"network"`
|
|
Expiry time.Duration `yaml:"expiry" json:"expiry"`
|
|
NoHostName bool `yaml:"no_hostname" json:"no_hostname"` // don't set the hostname
|
|
}
|
|
|
|
func (r *Range) Validate() error {
|
|
if !r.Start.Is4() {
|
|
return fmt.Errorf("range start %s is not a valid IPv4 address", r.Start)
|
|
}
|
|
|
|
if !r.End.Is4() {
|
|
return fmt.Errorf("range end %s is not a valid IPv4 address", r.End)
|
|
}
|
|
|
|
// Compare returns -1 if lhs < rhs, 0 if lhs == rhs, and 1 if lhs > rhs.
|
|
if r.End.Compare(r.Start) != 1 {
|
|
return fmt.Errorf("start address %s is not before end address %s", r.Start, r.End)
|
|
}
|
|
|
|
var err error
|
|
if !r.Network.IsValid() {
|
|
r.Network, err = r.Start.Prefix(DefaultMaskBits)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if !r.Network.Contains(r.Start) {
|
|
return fmt.Errorf("prefix %s does not contain start address %s", r.Network, r.Start)
|
|
}
|
|
|
|
if !r.Network.Contains(r.End) {
|
|
return fmt.Errorf("prefix %s does not contain end address %s", r.Network, r.End)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// this is probably dumb, but it's a one-time cost upfront on pool instantiation.
|
|
func (r *Range) numHosts() int {
|
|
cur := r.Start
|
|
hosts := 0
|
|
for cur.Compare(r.End) < 1 {
|
|
hosts++
|
|
cur = cur.Next()
|
|
}
|
|
|
|
return hosts
|
|
}
|