Skip to content

Commit

Permalink
Change EDNS_EXPIRE field to support zero length option data (Resolves m…
Browse files Browse the repository at this point in the history
…iekg#1292)

As per [RFC7134](https://datatracker.ietf.org/doc/html/rfc7314#section-2) the Expire
Option in queries should be zero-length. In the current implementation the field is
uint32 which always instatiates 4bytes for that field when packing to wire format.
For that reason we change the field to []uint8 so it can support 0-length and 4-byte
length option data.
  • Loading branch information
dmavrommatis committed Sep 13, 2021
1 parent ab67aa6 commit 8161c7d
Showing 1 changed file with 18 additions and 15 deletions.
33 changes: 18 additions & 15 deletions edns.go
Original file line number Diff line number Diff line change
Expand Up @@ -575,33 +575,36 @@ func (e *EDNS0_N3U) copy() EDNS0 { return &EDNS0_N3U{e.Code, e.AlgCode} }

// EDNS0_EXPIRE implements the EDNS0 option as described in RFC 7314.
type EDNS0_EXPIRE struct {
Code uint16 // Always EDNS0EXPIRE
Expire uint32
Code uint16 // Always EDNS0EXPIRE
Expire []uint8 // can be zero or 4 length
}

// Option implements the EDNS0 interface.
func (e *EDNS0_EXPIRE) Option() uint16 { return EDNS0EXPIRE }
func (e *EDNS0_EXPIRE) String() string { return strconv.FormatUint(uint64(e.Expire), 10) }
func (e *EDNS0_EXPIRE) copy() EDNS0 { return &EDNS0_EXPIRE{e.Code, e.Expire} }

func (e *EDNS0_EXPIRE) pack() ([]byte, error) {
b := make([]byte, 4)
binary.BigEndian.PutUint32(b, e.Expire)
return b, nil
if len(e.Expire) != 0 && len(e.Expire) != 4 {
return nil, errors.New("dns: expire length is not 0/4")
}
return e.Expire, nil
}

func (e *EDNS0_EXPIRE) unpack(b []byte) error {
if len(b) == 0 {
// zero-length EXPIRE query, see RFC 7314 Section 2
return nil
if len(b) != 0 && len(b) != 4 {
return errors.New("dns: expire length mismatch, want 0/4 but got " + strconv.Itoa(len(b)))
}
if len(b) < 4 {
return ErrBuf
}
e.Expire = binary.BigEndian.Uint32(b)
e.Expire = b
return nil
}

func (e *EDNS0_EXPIRE) String() (s string) {
if len(e.Expire) == 0 {
s = "<omitted>"
} else {
s = fmt.Sprintf("<%d>", binary.BigEndian.Uint32(e.Expire))
}
return s
}

// The EDNS0_LOCAL option is used for local/experimental purposes. The option
// code is recommended to be within the range [EDNS0LOCALSTART, EDNS0LOCALEND]
// (RFC6891), although any unassigned code can actually be used. The content of
Expand Down

0 comments on commit 8161c7d

Please sign in to comment.