From ec8d3d51d11f9eb196b9d0765ca8a84c6f225dd1 Mon Sep 17 00:00:00 2001 From: Alex Polvi Date: Mon, 15 Oct 2012 18:37:19 +0100 Subject: [PATCH] initial stab at edns update lease http://files.dns-sd.org/draft-sekar-dns-ul.txt --- README.markdown | 1 + client_test.go | 36 ++++++++++++++++++++++++++++++++++++ edns.go | 43 +++++++++++++++++++++++++++++++++++++++++++ msg.go | 5 +++++ 4 files changed, 85 insertions(+) diff --git a/README.markdown b/README.markdown index 9393ab0d..d950bd4f 100644 --- a/README.markdown +++ b/README.markdown @@ -87,6 +87,7 @@ be build with: `make -C ex`, or also with the `go` tool. * 5936 - AXFR * 6605 - ECDSA * xxxx - URI record (draft) +* xxxx - Dns Update Lease (draft) ## Loosely based upon diff --git a/client_test.go b/client_test.go index 1285808f..c8dc8f3e 100644 --- a/client_test.go +++ b/client_test.go @@ -99,3 +99,39 @@ func TestClientAXFRMultipleMessages(t *testing.T) { } } } + +// not really a test, but shows how to use update leases +func TestUpdateLeaseTSIG(t *testing.T) { + m := new(Msg) + m.SetUpdate("t.local.ip6.io.") + rr, _ := NewRR("t.local.ip6.io. 30 A 127.0.0.1") + rrs := make([]RR, 1) + rrs[0] = rr + m.AddRR(rrs) + + lease_rr := new(RR_OPT) + lease_rr.Hdr.Name = "." + lease_rr.Hdr.Rrtype = TypeOPT + e := new(EDNS0_UPDATE_LEASE) + e.Code = EDNS0UPDATELEASE + e.Lease = 120 + lease_rr.Option = append(lease_rr.Option, e) + m.Extra = append(m.Extra, lease_rr) + + c := new(Client) + m.SetTsig("polvi.", HmacMD5, 300, time.Now().Unix()) + c.TsigSecret = map[string]string{"polvi.": "pRZgBrBvI4NAHZYhxmhs/Q=="} + + w := new(reply) + w.client = c + w.addr = "127.0.0.1:53" + w.req = m + + if err := w.dial(); err != nil { + t.Fail() + } + if err := w.send(m); err != nil { + t.Fail() + } + +} diff --git a/edns.go b/edns.go index 41bd0224..6fb07c93 100644 --- a/edns.go +++ b/edns.go @@ -73,6 +73,8 @@ func (rr *RR_OPT) String() string { } case *EDNS0_SUBNET: s += "\n; SUBNET: " + o.String() + case *EDNS0_UPDATE_LEASE: + s += "\n; LEASE: " + o.String() } } return s @@ -278,3 +280,44 @@ func (e *EDNS0_SUBNET) String() (s string) { s += "/" + strconv.Itoa(int(e.SourceNetmask)) + "/" + strconv.Itoa(int(e.SourceScope)) return } + +// The UPDATE_LEASE EDNS0 (draft RFC) option is used to tell the server to set +// an expiration on an update RR. This is helpful for clients that cannot clean +// up after themselves. This is a draft RFC and more information can be found at +// http://files.dns-sd.org/draft-sekar-dns-ul.txt +// +// o := new(dns.RR_OPT) +// o.Hdr.Name = "." +// o.Hdr.Rrtype = dns.TypeOPT +// e := new(dns.EDNS0_UPDATE_LEASE) +// e.Code = dns.EDNS0UPDATELEASE +// e.Lease = 120 // in seconds +// o.Option = append(o.Option, e) +const EDNS0UPDATELEASE = 0x02 + +type EDNS0_UPDATE_LEASE struct { + Code uint16 // Always EDNS0UPDATELEASE + Lease uint32 +} + +func (e *EDNS0_UPDATE_LEASE) Option() uint16 { + return EDNS0UPDATELEASE +} + +// Copied: http://golang.org/src/pkg/net/dnsmsg.go +func (e *EDNS0_UPDATE_LEASE) pack() ([]byte, error) { + lease_byte := make([]byte, 4) + lease_byte[0] = byte(e.Lease >> 24) + lease_byte[1] = byte(e.Lease >> 16) + lease_byte[2] = byte(e.Lease >> 8) + lease_byte[3] = byte(e.Lease) + return lease_byte, nil +} + +func (e *EDNS0_UPDATE_LEASE) unpack(b []byte) { + e.Lease = uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3]) +} + +func (e *EDNS0_UPDATE_LEASE) String() string { + return strconv.Itoa(int(e.Lease)) +} diff --git a/msg.go b/msg.go index 8b108b3b..f3131b1a 100644 --- a/msg.go +++ b/msg.go @@ -699,6 +699,11 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err er e.unpack(msg[off1 : off1+int(optlen)]) edns = append(edns, e) off = off1 + int(optlen) + case EDNS0UPDATELEASE: + e := new(EDNS0_UPDATE_LEASE) + e.unpack(msg[off1 : off1+int(optlen)]) + edns = append(edns, e) + off = off1 + int(optlen) } fv.Set(reflect.ValueOf(edns)) // multiple EDNS codes?