diff --git a/iplib.go b/iplib.go index 52747f6..d9aaf2e 100644 --- a/iplib.go +++ b/iplib.go @@ -378,6 +378,22 @@ func IPToBigint(ip net.IP) *big.Int { return z } +// IPToBinarySlice returns the given net.IP as a []byte whose +// values are the binary representation of the IP +func IPToBinarySlice(ip net.IP) []byte { + var bits []byte + if EffectiveVersion(ip) == 4 { + ip = ForceIP4(ip) + } + for _, octet := range ip { + for i := 7; i >= 0; i-- { + bit := (octet >> i) & 1 + bits = append(bits, bit) + } + } + return bits +} + // IPToBinaryString returns the given net.IP as a binary string func IPToBinaryString(ip net.IP) string { var sa []string diff --git a/iplib_test.go b/iplib_test.go index fa594dd..5fbea03 100644 --- a/iplib_test.go +++ b/iplib_test.go @@ -1,6 +1,7 @@ package iplib import ( + "bytes" "math/big" "net" "reflect" @@ -22,13 +23,14 @@ func TestCopyIP(t *testing.T) { } var IPTests = []struct { - ipaddr net.IP - next net.IP - prev net.IP - intval uint32 - hexval string - inarpa string - binval string + ipaddr net.IP + next net.IP + prev net.IP + intval uint32 + hexval string + inarpa string + binval string + binslice []byte }{ { net.ParseIP("10.1.2.3"), @@ -38,6 +40,7 @@ var IPTests = []struct { "0a010203", "3.2.1.10.in-addr.arpa", "00001010.00000001.00000010.00000011", + []byte{0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1}, }, { net.ParseIP("10.1.2.255"), @@ -47,6 +50,7 @@ var IPTests = []struct { "0a0102ff", "255.2.1.10.in-addr.arpa", "00001010.00000001.00000010.11111111", + []byte{0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1}, }, { net.ParseIP("10.1.2.0"), @@ -56,6 +60,7 @@ var IPTests = []struct { "0a010200", "0.2.1.10.in-addr.arpa", "00001010.00000001.00000010.00000000", + []byte{0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { net.ParseIP("255.255.255.255"), @@ -65,6 +70,7 @@ var IPTests = []struct { "ffffffff", "255.255.255.255.in-addr.arpa", "11111111.11111111.11111111.11111111", + []byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, }, { net.ParseIP("0.0.0.0"), @@ -74,6 +80,7 @@ var IPTests = []struct { "00000000", "0.0.0.0.in-addr.arpa", "00000000.00000000.00000000.00000000", + []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, } @@ -113,6 +120,15 @@ func TestIPToHexString(t *testing.T) { } } +func TestIPToBinarySlice(t *testing.T) { + for i, tt := range IPTests { + b := IPToBinarySlice(tt.ipaddr) + if !bytes.Equal(b, tt.binslice) { + t.Errorf("[%d] expected %v, got %v", i, tt.binslice, b) + } + } +} + func TestIPToBinaryString(t *testing.T) { for i, tt := range IPTests { s := IPToBinaryString(tt.ipaddr) @@ -183,6 +199,7 @@ var IP6Tests = []struct { expand string inarpa string binval string + binslice []byte }{ { "2001:db8:85a3::8a2e:370:7334", @@ -195,6 +212,7 @@ var IP6Tests = []struct { "2001:0db8:85a3:0000:0000:8a2e:0370:7334", "4.3.3.7.0.7.3.0.e.2.a.8.0.0.0.0.0.0.0.0.3.a.5.8.8.b.d.0.1.0.0.2.ip6.arpa", "00100000.00000001.00001101.10111000.10000101.10100011.00000000.00000000.00000000.00000000.10001010.00101110.00000011.01110000.01110011.00110100", + []byte{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0}, }, { "::", @@ -207,6 +225,7 @@ var IP6Tests = []struct { "0000:0000:0000:0000:0000:0000:0000:0000", "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa", "00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000", + []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }, { "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", @@ -219,6 +238,7 @@ var IP6Tests = []struct { "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", "f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.ip6.arpa", "11111111.11111111.11111111.11111111.11111111.11111111.11111111.11111111.11111111.11111111.11111111.11111111.11111111.11111111.11111111.11111111", + []byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, }, } @@ -268,6 +288,15 @@ func TestUint64ToIP6(t *testing.T) { } } +func TestIP6ToBinarySlice(t *testing.T) { + for i, tt := range IP6Tests { + b := IPToBinarySlice(net.ParseIP(tt.ipaddr)) + if !bytes.Equal(b, tt.binslice) { + t.Errorf("[%d] expected %v, got %v", i, tt.binslice, b) + } + } +} + func TestIP6ToBinaryString(t *testing.T) { for i, tt := range IP6Tests { s := IPToBinaryString(net.ParseIP(tt.ipaddr))