1
0
mirror of https://github.com/StackExchange/dnscontrol.git synced 2024-05-11 05:55:12 +00:00

migrate code for github

This commit is contained in:
Craig Peterson
2016-08-22 18:31:50 -06:00
commit ef0bbf53af
359 changed files with 157476 additions and 0 deletions

113
transform/transform.go Normal file
View File

@ -0,0 +1,113 @@
package transform
import (
"fmt"
"net"
"strings"
)
type IpConversion struct {
Low, High, NewBase net.IP
NewIPs []net.IP
}
func ipToUint(i net.IP) (uint32, error) {
parts := i.To4()
if parts == nil || len(parts) != 4 {
return 0, fmt.Errorf("%s is not an ipv4 address", parts.String())
}
r := uint32(parts[0])<<24 | uint32(parts[1])<<16 | uint32(parts[2])<<8 | uint32(parts[3])
return r, nil
}
func UintToIP(u uint32) net.IP {
return net.IPv4(
byte((u>>24)&255),
byte((u>>16)&255),
byte((u>>8)&255),
byte((u)&255))
}
// DecodeTransformTable turns a string-encoded table into a list of conversions.
func DecodeTransformTable(transforms string) ([]IpConversion, error) {
result := []IpConversion{}
rows := strings.Split(transforms, ";")
for ri, row := range rows {
items := strings.Split(row, "~")
if len(items) != 4 {
return nil, fmt.Errorf("transform_table rows should have 4 elements. (%v) found in row (%v) of %#v\n", len(items), ri, transforms)
}
for i, item := range items {
items[i] = strings.TrimSpace(item)
}
con := IpConversion{
Low: net.ParseIP(items[0]),
High: net.ParseIP(items[1]),
NewBase: net.ParseIP(items[2]),
}
for _, ip := range strings.Split(items[3], ",") {
if ip == "" {
continue
}
addr := net.ParseIP(ip)
if addr == nil {
return nil, fmt.Errorf("%s is not a valid ip address", ip)
}
con.NewIPs = append(con.NewIPs, addr)
}
low, _ := ipToUint(con.Low)
high, _ := ipToUint(con.High)
if low > high {
return nil, fmt.Errorf("transform_table Low should be less than High. row (%v) %v>%v (%v)\n", ri, con.Low, con.High, transforms)
}
if con.NewBase != nil && con.NewIPs != nil {
return nil, fmt.Errorf("transform_table_rows should only specify one of NewBase or NewIP. Not both.")
}
result = append(result, con)
}
return result, nil
}
// TransformIP transforms a single ip address. If the transform results in multiple new targets, an error will be returned.
func TransformIP(address net.IP, transforms []IpConversion) (net.IP, error) {
ips, err := TransformIPToList(address, transforms)
if err != nil {
return nil, err
}
if len(ips) != 1 {
return nil, fmt.Errorf("Expect exactly one ip for TransformIP result. Got: %s", ips)
}
return ips[0], err
}
// TransformIPToList manipulates an net.IP based on a list of IpConversions. It can potentially expand one ip address into multiple addresses.
func TransformIPToList(address net.IP, transforms []IpConversion) ([]net.IP, error) {
thisIP, err := ipToUint(address)
if err != nil {
return nil, err
}
for _, conv := range transforms {
min, err := ipToUint(conv.Low)
if err != nil {
return nil, err
}
max, err := ipToUint(conv.High)
if err != nil {
return nil, err
}
if (thisIP >= min) && (thisIP <= max) {
if conv.NewIPs != nil {
return conv.NewIPs, nil
}
newbase, err := ipToUint(conv.NewBase)
if err != nil {
return nil, err
}
return []net.IP{UintToIP(newbase + (thisIP - min))}, nil
}
}
return []net.IP{address}, nil
}

213
transform/transform_test.go Normal file
View File

@ -0,0 +1,213 @@
package transform
import (
"net"
"testing"
)
func TestIPToUint(t *testing.T) {
ip := net.ParseIP("1.2.3.4")
u, err := ipToUint(ip)
if err != nil {
t.Fatal(err)
}
if u != 16909060 {
t.Fatalf("I to uint conversion failed. Should be 16909060. Got %d", u)
}
ip2 := UintToIP(u)
if !ip.Equal(ip2) {
t.Fatalf("IPs should be equal. %s is not %s", ip2, ip)
}
}
func Test_DecodeTransformTable_failures(t *testing.T) {
result, err := DecodeTransformTable("1.2.3.4 ~ 3.4.5.6")
if result != nil {
t.Errorf("expected nil, got (%v)\n", result)
}
if err == nil {
t.Error("expect error, got none")
}
}
func test_ip(t *testing.T, test string, expected string, actual net.IP) {
if !net.ParseIP(expected).Equal(actual) {
t.Errorf("Test %v: expected Low (%v), got (%v)\n", test, actual, expected)
}
}
func Test_DecodeTransformTable_0(t *testing.T) {
result, err := DecodeTransformTable("1.2.3.4 ~ 2.3.4.5 ~ 3.4.5.6 ~ ")
if err != nil {
t.Fatal(err)
}
if len(result) != 1 {
t.Errorf("Test %v: expected col length (%v), got (%v)\n", 1, 1, len(result))
}
test_ip(t, "low", "1.2.3.4", result[0].Low)
test_ip(t, "high", "2.3.4.5", result[0].High)
test_ip(t, "newBase", "3.4.5.6", result[0].NewBase)
//test_ip(t, "newIP", "", result[0].NewIPs)
}
func Test_DecodeTransformTable_1(t *testing.T) {
result, err := DecodeTransformTable("1.2.3.4~2.3.4.5~3.4.5.6 ~;8.7.6.5 ~ 9.8.7.6 ~ 7.6.5.4 ~ ")
if err != nil {
t.Fatal(err)
}
if len(result) != 2 {
t.Errorf("Test %v: expected col length (%v), got (%v)\n", 1, 2, len(result))
}
test_ip(t, "Low[0]", "1.2.3.4", result[0].Low)
test_ip(t, "High[0]", "2.3.4.5", result[0].High)
test_ip(t, "NewBase[0]", "3.4.5.6", result[0].NewBase)
//test_ip(t, "newIP[0]", "", result[0].NewIP)
test_ip(t, "Low[1]", "8.7.6.5", result[1].Low)
test_ip(t, "High[1]", "9.8.7.6", result[1].High)
test_ip(t, "NewBase[1]", "7.6.5.4", result[1].NewBase)
//test_ip(t, "newIP[1]", "", result[0].NewIP)
}
func Test_DecodeTransformTable_NewIP(t *testing.T) {
result, err := DecodeTransformTable("1.2.3.4 ~ 2.3.4.5 ~ ~ 3.4.5.6 ")
if err != nil {
t.Fatal(err)
}
if len(result) != 1 {
t.Errorf("Test %v: expected col length (%v), got (%v)\n", 1, 1, len(result))
}
test_ip(t, "low", "1.2.3.4", result[0].Low)
test_ip(t, "high", "2.3.4.5", result[0].High)
//test_ip(t, "newIP", "3.4.5.6", result[0].NewIP)
test_ip(t, "newBase", "", result[0].NewBase)
}
func Test_DecodeTransformTable_order(t *testing.T) {
raw := "9.8.7.6 ~ 8.7.6.5 ~ 7.6.5.4 ~"
result, err := DecodeTransformTable(raw)
if result != nil {
t.Errorf("Invalid range not detected: (%v)\n", raw)
}
if err == nil {
t.Error("expect error, got none")
}
}
func Test_DecodeTransformTable_Base_and_IP(t *testing.T) {
raw := "1.1.1.1~ 8.7.6.5 ~ 7.6.5.4 ~ 4.4.4.4"
result, err := DecodeTransformTable(raw)
if result != nil {
t.Errorf("NewBase and NewIP should not both be specified: (%v)\n", raw)
}
if err == nil {
t.Error("expect error, got none")
}
}
func Test_TransformIP(t *testing.T) {
var transforms1 = []IpConversion{{
Low: net.ParseIP("11.11.11.0"),
High: net.ParseIP("11.11.11.20"),
NewBase: net.ParseIP("99.99.99.0"),
}, {
Low: net.ParseIP("22.22.22.0"),
High: net.ParseIP("22.22.22.40"),
NewBase: net.ParseIP("99.99.99.100"),
}, {
Low: net.ParseIP("33.33.33.20"),
High: net.ParseIP("33.33.35.40"),
NewBase: net.ParseIP("100.100.100.0"),
}, {
Low: net.ParseIP("44.44.44.20"),
High: net.ParseIP("44.44.44.40"),
NewBase: net.ParseIP("100.100.100.40"),
}}
var tests = []struct {
experiment string
expected string
}{
{"11.11.11.0", "99.99.99.0"},
{"11.11.11.1", "99.99.99.1"},
{"11.11.11.11", "99.99.99.11"},
{"11.11.11.19", "99.99.99.19"},
{"11.11.11.20", "99.99.99.20"},
{"11.11.11.21", "11.11.11.21"},
{"22.22.22.22", "99.99.99.122"},
{"22.22.22.255", "22.22.22.255"},
{"33.33.33.0", "33.33.33.0"},
{"33.33.33.19", "33.33.33.19"},
{"33.33.33.20", "100.100.100.0"},
{"33.33.33.21", "100.100.100.1"},
{"33.33.33.33", "100.100.100.13"},
{"33.33.35.39", "100.100.102.19"},
{"33.33.35.40", "100.100.102.20"},
{"33.33.35.41", "33.33.35.41"},
{"44.44.44.24", "100.100.100.44"},
{"44.44.44.44", "44.44.44.44"},
}
for _, test := range tests {
experiment := net.ParseIP(test.experiment)
expected := net.ParseIP(test.expected)
actual, err := TransformIP(experiment, transforms1)
if err != nil {
t.Errorf("%v: got an err: %v\n", experiment, err)
}
if !expected.Equal(actual) {
t.Errorf("%v: expected (%v) got (%v)\n", experiment, expected, actual)
}
}
}
func Test_TransformIP_NewIP(t *testing.T) {
var transforms1 = []IpConversion{{
Low: net.ParseIP("11.11.11.0"),
High: net.ParseIP("11.11.11.20"),
NewIPs: []net.IP{net.ParseIP("1.1.1.1")},
}, {
Low: net.ParseIP("22.22.22.0"),
High: net.ParseIP("22.22.22.40"),
NewIPs: []net.IP{net.ParseIP("2.2.2.2")},
}, {
Low: net.ParseIP("33.33.33.20"),
High: net.ParseIP("33.33.35.40"),
NewIPs: []net.IP{net.ParseIP("3.3.3.3")},
},
}
var tests = []struct {
experiment string
expected string
}{
{"11.11.11.0", "1.1.1.1"},
{"11.11.11.1", "1.1.1.1"},
{"11.11.11.11", "1.1.1.1"},
{"11.11.11.19", "1.1.1.1"},
{"11.11.11.20", "1.1.1.1"},
{"11.11.11.21", "11.11.11.21"},
{"22.22.22.22", "2.2.2.2"},
{"22.22.22.255", "22.22.22.255"},
{"33.33.33.0", "33.33.33.0"},
{"33.33.33.19", "33.33.33.19"},
{"33.33.33.20", "3.3.3.3"},
{"33.33.33.21", "3.3.3.3"},
{"33.33.33.33", "3.3.3.3"},
{"33.33.35.39", "3.3.3.3"},
{"33.33.35.40", "3.3.3.3"},
{"33.33.35.41", "33.33.35.41"},
}
for _, test := range tests {
experiment := net.ParseIP(test.experiment)
expected := net.ParseIP(test.expected)
actual, err := TransformIP(experiment, transforms1)
if err != nil {
t.Errorf("%v: got an err: %v\n", experiment, err)
}
if !expected.Equal(actual) {
t.Errorf("%v: expected (%v) got (%v)\n", experiment, expected, actual)
}
}
}