61 lines
1.3 KiB
Go
61 lines
1.3 KiB
Go
package types
|
|
|
|
import (
|
|
"bytes"
|
|
"database/sql/driver"
|
|
"fmt"
|
|
"net"
|
|
)
|
|
|
|
type (
|
|
// Subnet is used to parse a subnet parameter.
|
|
Subnet net.IPNet
|
|
// IP is used to parse an IP parameter.
|
|
IP net.IP
|
|
)
|
|
|
|
// UnmarshalJSON parses a value into a subnet.
|
|
//
|
|
// It is also checked if the provided IP matches the network address
|
|
// of the subnet.
|
|
func (s *Subnet) UnmarshalJSON(in []byte) error {
|
|
in = bytes.Trim(in, `"`)
|
|
|
|
ip, ipnet, err := net.ParseCIDR(string(in))
|
|
if err != nil {
|
|
return fmt.Errorf("not a valid subnet")
|
|
}
|
|
if !ipnet.IP.Equal(ip) {
|
|
return fmt.Errorf("provided IP is not a subnet")
|
|
}
|
|
*s = Subnet(*ipnet)
|
|
return nil
|
|
}
|
|
|
|
// String returns the string representation of the subnet.
|
|
//
|
|
// The subnet is returned as the subnet address and prefix separated by `/`
|
|
// as defined in RFC 4632 and RFC 4291.
|
|
func (s *Subnet) String() string {
|
|
return (*net.IPNet)(s).String()
|
|
}
|
|
|
|
// Value implements the database Value interface.
|
|
//
|
|
// This function is needed so that a subnet can be inserted into
|
|
// the database without much casting.
|
|
func (s *Subnet) Value() (driver.Value, error) {
|
|
return s.String(), nil
|
|
}
|
|
|
|
func (i *IP) UnmarshalJSON(in []byte) error {
|
|
in = bytes.Trim(in, `"`)
|
|
|
|
ip := net.ParseIP(string(in))
|
|
if ip == nil {
|
|
return fmt.Errorf("not a valid ip")
|
|
}
|
|
*i = IP(ip)
|
|
return nil
|
|
}
|