mirror of
https://github.com/jeremyd/ergo.git
synced 2026-07-26 17:18:09 -07:00
refactor [dk]lines, implement #144
This commit is contained in:
@@ -9,6 +9,11 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
// subnet mask for an ipv6 /128:
|
||||
mask128 = net.CIDRMask(128, 128)
|
||||
)
|
||||
|
||||
// IPString returns a simple IP string from the given net.Addr.
|
||||
func IPString(addr net.Addr) string {
|
||||
addrStr := addr.String()
|
||||
@@ -94,3 +99,60 @@ func IsHostname(name string) bool {
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// NormalizeIPToNet represents an address (v4 or v6) as the v6 /128 CIDR
|
||||
// containing only it.
|
||||
func NormalizeIPToNet(addr net.IP) (network net.IPNet) {
|
||||
// represent ipv4 addresses as ipv6 addresses, using the 4-in-6 prefix
|
||||
// (actually this should be a no-op for any address returned by ParseIP)
|
||||
addr = addr.To16()
|
||||
// the network corresponding to this address is now an ipv6 /128:
|
||||
return net.IPNet{
|
||||
IP: addr,
|
||||
Mask: mask128,
|
||||
}
|
||||
}
|
||||
|
||||
// NormalizeNet normalizes an IPNet to a v6 CIDR, using the 4-in-6 prefix.
|
||||
// (this is like IP.To16(), but for IPNet instead of IP)
|
||||
func NormalizeNet(network net.IPNet) (result net.IPNet) {
|
||||
if len(network.IP) == 16 {
|
||||
return network
|
||||
}
|
||||
ones, _ := network.Mask.Size()
|
||||
return net.IPNet{
|
||||
IP: network.IP.To16(),
|
||||
// include the 96 bits of the 4-in-6 prefix
|
||||
Mask: net.CIDRMask(96+ones, 128),
|
||||
}
|
||||
}
|
||||
|
||||
// Given a network, produce a human-readable string
|
||||
// (i.e., CIDR if it's actually a network, IPv6 address if it's a v6 /128,
|
||||
// dotted quad if it's a v4 /32).
|
||||
func NetToNormalizedString(network net.IPNet) string {
|
||||
ones, bits := network.Mask.Size()
|
||||
if ones == bits && ones == len(network.IP)*8 {
|
||||
// either a /32 or a /128, output the address:
|
||||
return network.IP.String()
|
||||
}
|
||||
return network.String()
|
||||
}
|
||||
|
||||
// Parse a human-readable description (an address or CIDR, either v4 or v6)
|
||||
// into a normalized v6 net.IPNet.
|
||||
func NormalizedNetFromString(str string) (result net.IPNet, err error) {
|
||||
_, network, err := net.ParseCIDR(str)
|
||||
if err == nil {
|
||||
return NormalizeNet(*network), nil
|
||||
}
|
||||
ip := net.ParseIP(str)
|
||||
if ip == nil {
|
||||
err = &net.AddrError{
|
||||
Err: "Couldn't interpret as either CIDR or address",
|
||||
Addr: str,
|
||||
}
|
||||
return
|
||||
}
|
||||
return NormalizeIPToNet(ip), nil
|
||||
}
|
||||
|
||||
@@ -4,8 +4,16 @@
|
||||
|
||||
package utils
|
||||
|
||||
import "net"
|
||||
import "reflect"
|
||||
import "testing"
|
||||
|
||||
func assertEqual(supplied, expected interface{}, t *testing.T) {
|
||||
if !reflect.DeepEqual(supplied, expected) {
|
||||
t.Errorf("expected %v but got %v", expected, supplied)
|
||||
}
|
||||
}
|
||||
|
||||
// hostnames from https://github.com/DanielOaks/irc-parser-tests
|
||||
var (
|
||||
goodHostnames = []string{
|
||||
@@ -47,3 +55,94 @@ func TestIsHostname(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizeToNet(t *testing.T) {
|
||||
a := net.ParseIP("8.8.8.8")
|
||||
b := net.ParseIP("8.8.4.4")
|
||||
if a == nil || b == nil {
|
||||
panic("something has gone very wrong")
|
||||
}
|
||||
|
||||
aNetwork := NormalizeIPToNet(a)
|
||||
bNetwork := NormalizeIPToNet(b)
|
||||
|
||||
assertEqual(aNetwork.Contains(a), true, t)
|
||||
assertEqual(bNetwork.Contains(b), true, t)
|
||||
assertEqual(aNetwork.Contains(b), false, t)
|
||||
assertEqual(bNetwork.Contains(a), false, t)
|
||||
|
||||
c := net.ParseIP("2001:4860:4860::8888")
|
||||
d := net.ParseIP("2001:db8::1")
|
||||
if c == nil || d == nil {
|
||||
panic("something has gone very wrong")
|
||||
}
|
||||
|
||||
cNetwork := NormalizeIPToNet(c)
|
||||
dNetwork := NormalizeIPToNet(d)
|
||||
|
||||
assertEqual(cNetwork.Contains(c), true, t)
|
||||
assertEqual(dNetwork.Contains(d), true, t)
|
||||
assertEqual(dNetwork.Contains(c), false, t)
|
||||
assertEqual(dNetwork.Contains(a), false, t)
|
||||
assertEqual(cNetwork.Contains(b), false, t)
|
||||
assertEqual(aNetwork.Contains(c), false, t)
|
||||
assertEqual(bNetwork.Contains(c), false, t)
|
||||
|
||||
assertEqual(NetToNormalizedString(aNetwork), "8.8.8.8", t)
|
||||
assertEqual(NetToNormalizedString(bNetwork), "8.8.4.4", t)
|
||||
assertEqual(NetToNormalizedString(cNetwork), "2001:4860:4860::8888", t)
|
||||
assertEqual(NetToNormalizedString(dNetwork), "2001:db8::1", t)
|
||||
}
|
||||
|
||||
func TestNormalizedNetToString(t *testing.T) {
|
||||
_, network, err := net.ParseCIDR("8.8.0.0/16")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
assertEqual(NetToNormalizedString(*network), "8.8.0.0/16", t)
|
||||
|
||||
normalized := NormalizeNet(*network)
|
||||
assertEqual(normalized.Contains(net.ParseIP("8.8.4.4")), true, t)
|
||||
assertEqual(normalized.Contains(net.ParseIP("1.1.1.1")), false, t)
|
||||
assertEqual(NetToNormalizedString(normalized), "8.8.0.0/16", t)
|
||||
|
||||
_, network, err = net.ParseCIDR("8.8.4.4/32")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
assertEqual(NetToNormalizedString(*network), "8.8.4.4", t)
|
||||
|
||||
normalized = NormalizeNet(*network)
|
||||
assertEqual(normalized.Contains(net.ParseIP("8.8.4.4")), true, t)
|
||||
assertEqual(normalized.Contains(net.ParseIP("8.8.8.8")), false, t)
|
||||
assertEqual(NetToNormalizedString(normalized), "8.8.4.4", t)
|
||||
}
|
||||
|
||||
func TestNormalizedNet(t *testing.T) {
|
||||
_, network, err := net.ParseCIDR("::ffff:8.8.4.4/128")
|
||||
assertEqual(err, nil, t)
|
||||
assertEqual(NetToNormalizedString(*network), "8.8.4.4", t)
|
||||
|
||||
normalizedNet := NormalizeIPToNet(net.ParseIP("8.8.4.4"))
|
||||
assertEqual(NetToNormalizedString(normalizedNet), "8.8.4.4", t)
|
||||
|
||||
_, network, err = net.ParseCIDR("::ffff:8.8.0.0/112")
|
||||
assertEqual(err, nil, t)
|
||||
assertEqual(NetToNormalizedString(*network), "8.8.0.0/16", t)
|
||||
_, v4Network, err := net.ParseCIDR("8.8.0.0/16")
|
||||
assertEqual(err, nil, t)
|
||||
normalizedNet = NormalizeNet(*v4Network)
|
||||
assertEqual(NetToNormalizedString(normalizedNet), "8.8.0.0/16", t)
|
||||
}
|
||||
|
||||
func TestNormalizedNetFromString(t *testing.T) {
|
||||
network, err := NormalizedNetFromString("8.8.4.4/16")
|
||||
assertEqual(err, nil, t)
|
||||
assertEqual(NetToNormalizedString(network), "8.8.0.0/16", t)
|
||||
assertEqual(network.Contains(net.ParseIP("8.8.8.8")), true, t)
|
||||
|
||||
network, err = NormalizedNetFromString("2001:0db8::1")
|
||||
assertEqual(err, nil, t)
|
||||
assertEqual(NetToNormalizedString(network), "2001:db8::1", t)
|
||||
assertEqual(network.Contains(net.ParseIP("2001:0db8::1")), true, t)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user