diff --git a/src/xip/xip.go b/src/xip/xip.go index c2b895d..9fde092 100644 --- a/src/xip/xip.go +++ b/src/xip/xip.go @@ -10,6 +10,7 @@ import ( // https://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses var ipv4RE= regexp.MustCompile(`(^|[.-])(((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])[.-]){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))($|[.-])`) +var ipv6RE= regexp.MustCompile(`(^|[.-])(([0-9a-fA-F]{1,4}-){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}-){1,7}-|([0-9a-fA-F]{1,4}-){1,6}-[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}-){1,5}(-[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}-){1,4}(-[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}-){1,3}(-[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}-){1,2}(-[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}-((-[0-9a-fA-F]{1,4}){1,6})|-((-[0-9a-fA-F]{1,4}){1,7}|-)|fe80-(-[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|--(ffff(-0{1,4}){0,1}-){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}-){1,4}-((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))($|[.-])`) func NameToA (fqdnString string) (dnsmessage.AResource, error) { fqdn:=[]byte(fqdnString) @@ -23,3 +24,21 @@ func NameToA (fqdnString string) (dnsmessage.AResource, error) { return dnsmessage.AResource{A: [4]byte{ipv4address[0], ipv4address[1], ipv4address[2], ipv4address[3]}}, nil } + +func NameToAAAA (fqdnString string) (dnsmessage.AAAAResource, error) { + fqdn:=[]byte(fqdnString) + if ! ipv6RE.Match(fqdn) { + return dnsmessage.AAAAResource{}, errors.New("ENOTFOUND") // I can't help it; I love the old-style UNIX errors + } + + match := string(ipv6RE.FindSubmatch(fqdn)[2]) + match = strings.Replace(match, "-", ":", -1) + ipv16address := net.ParseIP(match).To16() + + AAAAR := dnsmessage.AAAAResource{} + for i, _ := range ipv16address { + AAAAR.AAAA[i] = ipv16address[i] + } + return AAAAR, nil +} + diff --git a/src/xip/xip_test.go b/src/xip/xip_test.go index 5d99558..79bef8a 100644 --- a/src/xip/xip_test.go +++ b/src/xip/xip_test.go @@ -32,9 +32,7 @@ var _ = Describe("Xip", func() { DescribeTable("when it does not match an IP address", func(fqdn string) { _, err := xip.NameToA(fqdn) - //ipv4Answer, err := xip.NameToA(fqdn) Expect(err).To(MatchError(errors.New("ENOTFOUND"))) - //Expect(ipv4Answer).To(Equal(dnsmessage.AResource{})) // is this important to test? }, Entry("empty string", ""), Entry("bare domain", "nono.io"), @@ -44,4 +42,32 @@ var _ = Describe("Xip", func() { Entry("too big", "256.254.253.252"), ) }) -}) \ No newline at end of file + Describe("NameToAAAA()", func() { + DescribeTable("when it succeeds", + func(fqdn string, expectedAAAA dnsmessage.AAAAResource) { + ipv6Answer, err := xip.NameToAAAA(fqdn) + Expect(err).To(Not(HaveOccurred())) + Expect(ipv6Answer).To(Equal(expectedAAAA)) + }, + // dashes only + Entry("loopback", "--1", dnsmessage.AAAAResource{AAAA: [16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}}), + Entry("ff with domain", "fffe-fdfc-fbfa-f9f8-f7f6-f5f4-f3f2-f1f0.com", dnsmessage.AAAAResource{AAAA: [16]byte{255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240}}), + Entry("ff with domain and pre", "www.fffe-fdfc-fbfa-f9f8-f7f6-f5f4-f3f2-f1f0.com", dnsmessage.AAAAResource{AAAA: [16]byte{255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240}}), + Entry("ff with domain dashes", "1.www-fffe-fdfc-fbfa-f9f8-f7f6-f5f4-f3f2-f1f0-1.com", dnsmessage.AAAAResource{AAAA: [16]byte{255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240}}), + ) + DescribeTable("when it does not match an IP address", + func(fqdn string) { + _, err := xip.NameToAAAA(fqdn) + //ipv4Answer, err := xip.NameToA(fqdn) + Expect(err).To(MatchError(errors.New("ENOTFOUND"))) + //Expect(ipv4Answer).To(Equal(dnsmessage.AAAAResource{})) // is this important to test? + }, + Entry("empty string", ""), + Entry("bare domain", "nono.io"), + Entry("canonical domain", "sslip.io"), + Entry("www", "www.sslip.io"), + Entry("a 1 without double-dash", "-1"), + Entry("too big", "--g"), + ) + }) +})