2019-10-01 12:22:30 -03:00

84 lines
1.8 KiB
Go

package banman
import (
"io"
"net"
)
// ipType represents the different types of IP addresses supported by the
// BanStore interface.
type ipType = byte
const (
// ipv4 represents an IP address of type IPv4.
ipv4 ipType = 0
// ipv6 represents an IP address of type IPv6.
ipv6 ipType = 1
)
// encodeIPNet serializes the IP network into the given reader.
func encodeIPNet(w io.Writer, ipNet *net.IPNet) error {
// Determine the appropriate IP type for the IP address contained in the
// network.
var (
ip []byte
ipType ipType
)
switch {
case ipNet.IP.To4() != nil:
ip = ipNet.IP.To4()
ipType = ipv4
case ipNet.IP.To16() != nil:
ip = ipNet.IP.To16()
ipType = ipv6
default:
return ErrUnsupportedIP
}
// Write the IP type first in order to properly identify it when
// deserializing it, followed by the IP itself and its mask.
if _, err := w.Write([]byte{ipType}); err != nil {
return err
}
if _, err := w.Write(ip); err != nil {
return err
}
if _, err := w.Write([]byte(ipNet.Mask)); err != nil {
return err
}
return nil
}
// decodeIPNet deserialized an IP network from the given reader.
func decodeIPNet(r io.Reader) (*net.IPNet, error) {
// Read the IP address type and determine whether it is supported.
var ipType [1]byte
if _, err := r.Read(ipType[:]); err != nil {
return nil, err
}
var ipLen int
switch ipType[0] {
case ipv4:
ipLen = net.IPv4len
case ipv6:
ipLen = net.IPv6len
default:
return nil, ErrUnsupportedIP
}
// Once we have the type and its corresponding length, attempt to read
// it and its mask.
ip := make([]byte, ipLen)
if _, err := r.Read(ip[:]); err != nil {
return nil, err
}
mask := make([]byte, ipLen)
if _, err := r.Read(mask[:]); err != nil {
return nil, err
}
return &net.IPNet{IP: ip, Mask: mask}, nil
}