Repository: miekg/dns
Pull request #1301 (2021-09-27 12:33:00)

Added support for ENUM Source-URI Extension
Hi Miek,

Added the ENUM Source-URI Extension described here: https://datatracker.ietf.org/doc/html/draft-kaplan-enum-source-uri-00

Thanks for this great project!


Patch:
diff --git a/edns.go b/edns.go
index c9181783..d070e41b 100644
--- a/edns.go
+++ b/edns.go
@@ -14,6 +14,7 @@ const (
 	EDNS0LLQ          = 0x1     // long lived queries: http://tools.ietf.org/html/draft-sekar-dns-llq-01
 	EDNS0UL           = 0x2     // update lease draft: http://files.dns-sd.org/draft-sekar-dns-ul.txt
 	EDNS0NSID         = 0x3     // nsid (See RFC 5001)
+	EDNS0ESU          = 0x4     // ENUM Source-URI draft: https://datatracker.ietf.org/doc/html/draft-kaplan-enum-source-uri-00
 	EDNS0DAU          = 0x5     // DNSSEC Algorithm Understood
 	EDNS0DHU          = 0x6     // DS Hash Understood
 	EDNS0N3U          = 0x7     // NSEC3 Hash Understood
@@ -56,6 +57,8 @@ func makeDataOpt(code uint16) EDNS0 {
 		return new(EDNS0_PADDING)
 	case EDNS0EDE:
 		return new(EDNS0_EDE)
+	case EDNS0ESU:
+		return &EDNS0_ESU{Code: EDNS0ESU}
 	default:
 		e := new(EDNS0_LOCAL)
 		e.Code = code
@@ -111,6 +114,8 @@ func (rr *OPT) String() string {
 			s += "\n; PADDING: " + o.String()
 		case *EDNS0_EDE:
 			s += "\n; EDE: " + o.String()
+		case *EDNS0_ESU:
+			s += "\n; ESU: " + o.String()
 		}
 	}
 	return s
@@ -819,3 +824,19 @@ func (e *EDNS0_EDE) unpack(b []byte) error {
 	e.ExtraText = string(b[2:])
 	return nil
 }
+
+// The EDNS0_ESU option for ENUM Source-URI Extension
+type EDNS0_ESU struct {
+	Code uint16
+	Uri  string
+}
+
+// Option implements the EDNS0 interface.
+func (e *EDNS0_ESU) Option() uint16        { return EDNS0ESU }
+func (e *EDNS0_ESU) String() string        { return e.Uri }
+func (e *EDNS0_ESU) copy() EDNS0           { return &EDNS0_ESU{e.Code, e.Uri} }
+func (e *EDNS0_ESU) pack() ([]byte, error) { return []byte(e.Uri), nil }
+func (e *EDNS0_ESU) unpack(b []byte) error {
+	e.Uri = string(b)
+	return nil
+}


Test patch:
diff --git a/edns_test.go b/edns_test.go
index ab2a3b1f..dc4ea7b3 100644
--- a/edns_test.go
+++ b/edns_test.go
@@ -158,3 +158,37 @@ func TestZ(t *testing.T) {
 		t.Error("expected DO to be set")
 	}
 }
+
+func TestEDNS0_ESU(t *testing.T) {
+	p := []byte{
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x29, 0x04,
+		0xC4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00,
+		0x04, 0x00, 0x24, 0x73, 0x69, 0x70, 0x3A, 0x2B,
+		0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
+		0x39, 0x40, 0x74, 0x65, 0x73, 0x74, 0x2E, 0x63,
+		0x6F, 0x6D, 0x3B, 0x75, 0x73, 0x65, 0x72, 0x3D,
+		0x63, 0x67, 0x72, 0x61, 0x74, 0x65, 0x73,
+	}
+
+	m := new(Msg)
+	if err := m.Unpack(p); err != nil {
+		t.Fatalf("failed to unpack: %v", err)
+	}
+	opt := m.IsEdns0()
+	if opt == nil {
+		t.Fatalf("expected edns0 option")
+	}
+	if len(opt.Option) != 1 {
+		t.Fatalf("expected only one option: %v", opt.Option)
+	}
+	edns0 := opt.Option[0]
+	esu, ok := edns0.(*EDNS0_ESU)
+	if !ok {
+		t.Fatalf("expected option of type EDNS0_ESU, got %t", edns0)
+	}
+	expect := "sip:+123456789@test.com;user=cgrates"
+	if esu.Uri != expect {
+		t.Errorf("unpacked option is different; expected %v, got %v", expect, esu.Uri)
+	}
+}