diff --git a/README.markdown b/README.markdown index c23dc109..64556e8e 100644 --- a/README.markdown +++ b/README.markdown @@ -9,12 +9,13 @@ implemented in the library. Features: * UDP/TCP queries, IPv4 and IPv6; -* TSIG; -* EDNS0; -* AXFR/IXFR; -* DNS name compression; * Client and server side programming (mimicking the http package); * Asynchronous queries for client and server; +* DNSSEC; +* EDNS0; +* AXFR/IXFR; +* TSIG; +* DNS name compression; * RFC 1035 zone file parsing. Sample programs can be found in the `_examples` directory. They can @@ -50,7 +51,7 @@ Miek Gieben - 2010-2012 - miek@miek.nl * 4635 - HMAC SHA TSIG * 4892 - id.server * 5001 - NSID -* 5155 - NSEC +* 5155 - NSEC3 * 5933 - GOST * 5936 - AXFR * xxxx - ECDSA diff --git a/_examples/reflect/reflect.go b/_examples/reflect/reflect.go index f229f29a..d2c265f9 100644 --- a/_examples/reflect/reflect.go +++ b/_examples/reflect/reflect.go @@ -75,12 +75,28 @@ func handleReflect(w dns.ResponseWriter, r *dns.Msg) { m.Extra = append(m.Extra, t) } + nsec3 := new(dns.RR_NSEC3) + nsec3.Hdr = dns.RR_Header{Name: dom, Rrtype: dns.TypeNSEC3, Class: dns.ClassINET, Ttl: 0} + nsec3.Hash = dns.SHA1 + nsec3.Flags = 0 + nsec3.Iterations = 1 + nsec3.Salt = "AABB" + nsec3.SaltLength = uint8(len(nsec3.Salt)/2) + nsec3.NextDomain = "miek.nl." +// nsec3.TypeBitMap = []uint16{dns.TypeA, dns.TypeNS, dns.TypeMX, dns.TypeTXT, 4000, 4001} +// nsec3.TypeBitMap = []uint16{dns.TypeA, dns.TypeNS, dns.TypeMX, dns.TypeTXT} + nsec3.TypeBitMap = []uint16{dns.TypeA, dns.TypeNS, dns.TypeSOA} + nsec3.HashNames("miek.nl.") + m.Extra = append(m.Extra, nsec3) b, ok := m.Pack() + fmt.Printf("%v\n", m.String()) if !ok { log.Print("Packing failed") - //write formerr back? - return + m.SetRcode(r, dns.RcodeServerFailure) + m.Extra = nil + m.Answer = nil + b, _ = m.Pack() } w.Write(b) } diff --git a/msg.go b/msg.go index 3c249eb1..3cf5206e 100644 --- a/msg.go +++ b/msg.go @@ -16,6 +16,7 @@ import ( "encoding/base32" "encoding/base64" "encoding/hex" + "fmt" "math/rand" "net" "reflect" @@ -408,11 +409,34 @@ func packStructValue(val reflect.Value, msg []byte, off int, compression map[str off++ } case "NSEC": // NSEC/NSEC3 + // This is the uint16 type bitmap + // TODO(mg): overflow + lastwindow := uint16(0) + octet := uint16(0) for j := 0; j < val.Field(i).Len(); j++ { - var _ = byte(fv.Index(j).Uint()) + t := uint16((fv.Index(j).Uint())) + window := uint16(t / 256) + if lastwindow != window { + // New window + off += 2 + int(octet) + } + octet := (t - window*256) / 8 + bit := t - (window * 256) - (octet * 8) + + println("Setting window", off, "to", byte(window)) + msg[off] = byte(window) + println("Setting octet", off+1, "to", byte(octet+1)) + msg[off+1] = byte(octet+1) + println("Setting value", off+1+1+int(octet), "to", byte(1< lenmsg { diff --git a/update.go b/update.go index 84fd12bb..3c73c891 100644 --- a/update.go +++ b/update.go @@ -11,13 +11,13 @@ // // 3.2.4 - Table Of Metavalues Used In Prerequisite Section // -// CLASS TYPE RDATA Meaning Function -// ---------------------------------------------------------------------------- -// ANY ANY empty Name is in use NameUsed -// ANY rrset empty RRset exists (value independent) RRsetUsedNoRdata -// NONE ANY empty Name is not in use NameNotUsed -// NONE rrset empty RRset does not exist RRsetNotUsed -// zone rrset rr RRset exists (value dependent) RRsetUsedRdata +// CLASS TYPE RDATA Meaning Function +// -------------------------------------------------------------- +// ANY ANY empty Name is in use NameUsed +// ANY rrset empty RRset exists (value indep) RRsetUsedNoRdata +// NONE ANY empty Name is not in use NameNotUsed +// NONE rrset empty RRset does not exist RRsetNotUsed +// zone rrset rr RRset exists (value dep) RRsetUsedRdata // // The prerequisite section can also be left empty. // If you have decided an the prerequisites you can tell what RRs should @@ -25,16 +25,17 @@ // what function to call. // 3.4.2.6 - Table Of Metavalues Used In Update Section // -// CLASS TYPE RDATA Meaning Function -// ------------------------------------------------------------------------- -// ANY ANY empty Delete all RRsets from a name NameDelete -// ANY rrset empty Delete an RRset RRsetDelete -// NONE rrset rr Delete an RR from an RRset RRsetDeleteRR -// zone rrset rr Add to an RRset RRsetAddRdata +// CLASS TYPE RDATA Meaning Function +// --------------------------------------------------------------- +// ANY ANY empty Delete all RRsets from name NameDelete +// ANY rrset empty Delete an RRset RRsetDelete +// NONE rrset rr Delete an RR from RRset RRsetDeleteRR +// zone rrset rr Add to an RRset RRsetAddRdata // package dns -// NewUpdate creates a new DNS update packet, which is a normal DNS message. +// NewUpdate creates a new DNS update packet. This returns a normal +// dns *Msg, but sets some options. func NewUpdate(zone string, class uint16) *Msg { u := new(Msg) u.MsgHdr.Response = false @@ -49,13 +50,13 @@ func NewUpdate(zone string, class uint16) *Msg { // // 3.2.4 - Table Of Metavalues Used In Prerequisite Section // -// CLASS TYPE RDATA Meaning Function -// ---------------------------------------------------------------------- -// ANY ANY empty Name is in use NameUsed -// ANY rrset empty RRset exists (value independent) RRsetUsedNoRdata -// NONE ANY empty Name is not in use NameNotUsed -// NONE rrset empty RRset does not exist RRsetNotUsed -// zone rrset rr RRset exists (value dependent) RRsetUsedRdata +// CLASS TYPE RDATA Meaning Function +// --------------------------------------------------------------- +// ANY ANY empty Name is in use NameUsed +// ANY rrset empty RRset exists (value indep) RRsetUsedNoRdata +// NONE ANY empty Name is not in use NameNotUsed +// NONE rrset empty RRset does not exist RRsetNotUsed +// zone rrset rr RRset exists (value dep) RRsetUsedRdata // NameUsed sets the RRs in the prereq section to // "Name is in use" RRs. RFC 2136 section 2.4.4. @@ -116,12 +117,12 @@ func (u *Msg) RRsetNotUsed(rr []RR) { // // 3.4.2.6 - Table Of Metavalues Used In Update Section // -// CLASS TYPE RDATA Meaning Function -// -------------------------------------------------------------------------- -// ANY ANY empty Delete all RRsets from a name NameDelete -// ANY rrset empty Delete an RRset RRsetDelete -// NONE rrset rr Delete an RR from an RRset RRsetDeleteRR -// zone rrset rr Add to an RRset RRsetAddRdata +// CLASS TYPE RDATA Meaning Function +// ----------------------------------------------------------------- +// ANY ANY empty Delete all RRsets from name NameDelete +// ANY rrset empty Delete an RRset RRsetDelete +// NONE rrset rr Delete an RR from RRset RRsetDeleteRR +// zone rrset rr Add to an RRset RRsetAddRdata // RRsetAddRdata adds an complete RRset, see RFC 2136 section 2.5.1 func (u *Msg) RRsetAddRdata(rr []RR) {