diff --git a/edns.go b/edns.go index d244f7c6..75a07ea3 100644 --- a/edns.go +++ b/edns.go @@ -47,7 +47,8 @@ func (rr *OPT) String() string { switch o.(type) { case *EDNS0_NSID: s += "\n; NSID: " + o.String() - h, e := o.pack() + h := make([]byte, o.Len()) + _, e := o.Pack(h) var r string if e == nil { for _, c := range h { @@ -82,8 +83,7 @@ func (rr *OPT) len(off int, compression map[string]struct{}) int { l := rr.Hdr.len(off, compression) for _, o := range rr.Option { l += 4 // Account for 2-byte option code and 2-byte option length. - lo, _ := o.pack() - l += len(lo) + l += o.Len() } return l } @@ -152,15 +152,19 @@ func (rr *OPT) SetDo(do ...bool) { type EDNS0 interface { // Option returns the option code for the option. Option() uint16 - // pack returns the bytes of the option data. - pack() ([]byte, error) - // unpack sets the data as found in the buffer. Is also sets + // Len returns the length (number of bytes) of the option data when + // packed + Len() int + // Pack writes the option data into the buffer. The buffer should be at + // least Len() bytes long. Returns the number of bytes written. + Pack(b []byte) (int, error) + // Unpack sets the data as found in the buffer. Is also sets // the length of the slice as the length of the option data. - unpack([]byte) error + Unpack([]byte) (int, error) // String returns the string representation of the option. String() string // copy returns a deep-copy of the option. - copy() EDNS0 + Copy() EDNS0 } // EDNS0_NSID option is used to retrieve a nameserver @@ -180,19 +184,20 @@ type EDNS0_NSID struct { Nsid string // This string needs to be hex encoded } -func (e *EDNS0_NSID) pack() ([]byte, error) { - h, err := hex.DecodeString(e.Nsid) - if err != nil { - return nil, err - } - return h, nil +func (e *EDNS0_NSID) Len() int { + return hex.DecodedLen(len(e.Nsid)) +} + +func (e *EDNS0_NSID) Pack(b []byte) (int, error) { + nsid := []byte(e.Nsid) + return hex.Decode(nsid, b) } // Option implements the EDNS0 interface. -func (e *EDNS0_NSID) Option() uint16 { return EDNS0NSID } // Option returns the option code. -func (e *EDNS0_NSID) unpack(b []byte) error { e.Nsid = hex.EncodeToString(b); return nil } -func (e *EDNS0_NSID) String() string { return e.Nsid } -func (e *EDNS0_NSID) copy() EDNS0 { return &EDNS0_NSID{e.Code, e.Nsid} } +func (e *EDNS0_NSID) Option() uint16 { return EDNS0NSID } // Option returns the option code. +func (e *EDNS0_NSID) Unpack(b []byte) (int, error) { e.Nsid = hex.EncodeToString(b); return len(b), nil } +func (e *EDNS0_NSID) String() string { return e.Nsid } +func (e *EDNS0_NSID) Copy() EDNS0 { return &EDNS0_NSID{e.Code, e.Nsid} } // EDNS0_SUBNET is the subnet option that is used to give the remote nameserver // an idea of where the client lives. See RFC 7871. It can then give back a different @@ -225,77 +230,82 @@ type EDNS0_SUBNET struct { // Option implements the EDNS0 interface. func (e *EDNS0_SUBNET) Option() uint16 { return EDNS0SUBNET } -func (e *EDNS0_SUBNET) pack() ([]byte, error) { - b := make([]byte, 4) +func (e *EDNS0_SUBNET) Len() int { + return 4 + int((e.SourceNetmask + 8 - 1) / 8) // division rounding up +} + +func (e *EDNS0_SUBNET) Pack(b []byte) (int, error) { binary.BigEndian.PutUint16(b[0:], e.Family) b[2] = e.SourceNetmask b[3] = e.SourceScope + var copied int = 0 switch e.Family { case 0: // "dig" sets AddressFamily to 0 if SourceNetmask is also 0 // We might don't need to complain either if e.SourceNetmask != 0 { - return nil, errors.New("dns: bad address family") + return 0, errors.New("dns: bad address family") } case 1: if e.SourceNetmask > net.IPv4len*8 { - return nil, errors.New("dns: bad netmask") + return 0, errors.New("dns: bad netmask") } if len(e.Address.To4()) != net.IPv4len { - return nil, errors.New("dns: bad address") + return 0, errors.New("dns: bad address") } ip := e.Address.To4().Mask(net.CIDRMask(int(e.SourceNetmask), net.IPv4len*8)) - needLength := (e.SourceNetmask + 8 - 1) / 8 // division rounding up - b = append(b, ip[:needLength]...) + needLength := int((e.SourceNetmask + 8 - 1) / 8) // division rounding up + copied = copy(b[4:], ip[:needLength]) case 2: if e.SourceNetmask > net.IPv6len*8 { - return nil, errors.New("dns: bad netmask") + return 0, errors.New("dns: bad netmask") } if len(e.Address) != net.IPv6len { - return nil, errors.New("dns: bad address") + return 0, errors.New("dns: bad address") } ip := e.Address.Mask(net.CIDRMask(int(e.SourceNetmask), net.IPv6len*8)) - needLength := (e.SourceNetmask + 8 - 1) / 8 // division rounding up - b = append(b, ip[:needLength]...) + needLength := int((e.SourceNetmask + 8 - 1) / 8) // division rounding up + copied = copy(b[4:], ip[:needLength]) default: - return nil, errors.New("dns: bad address family") + return 0, errors.New("dns: bad address family") } - return b, nil + return 4 + copied, nil } -func (e *EDNS0_SUBNET) unpack(b []byte) error { +func (e *EDNS0_SUBNET) Unpack(b []byte) (int, error) { if len(b) < 4 { - return ErrBuf + return 0, ErrBuf } e.Family = binary.BigEndian.Uint16(b) e.SourceNetmask = b[2] e.SourceScope = b[3] + var l int = 0 switch e.Family { case 0: // "dig" sets AddressFamily to 0 if SourceNetmask is also 0 // It's okay to accept such a packet if e.SourceNetmask != 0 { - return errors.New("dns: bad address family") + return 0, errors.New("dns: bad address family") } e.Address = net.IPv4(0, 0, 0, 0) case 1: if e.SourceNetmask > net.IPv4len*8 || e.SourceScope > net.IPv4len*8 { - return errors.New("dns: bad netmask") + return 0, errors.New("dns: bad netmask") } addr := make(net.IP, net.IPv4len) - copy(addr, b[4:]) + l = copy(addr, b[4:]) e.Address = addr.To16() case 2: if e.SourceNetmask > net.IPv6len*8 || e.SourceScope > net.IPv6len*8 { - return errors.New("dns: bad netmask") + return 0, errors.New("dns: bad netmask") } addr := make(net.IP, net.IPv6len) - copy(addr, b[4:]) + l = copy(addr, b[4:]) e.Address = addr default: - return errors.New("dns: bad address family") + return 0, errors.New("dns: bad address family") } - return nil + return 4 + l, nil } func (e *EDNS0_SUBNET) String() (s string) { @@ -310,7 +320,7 @@ func (e *EDNS0_SUBNET) String() (s string) { return } -func (e *EDNS0_SUBNET) copy() EDNS0 { +func (e *EDNS0_SUBNET) Copy() EDNS0 { return &EDNS0_SUBNET{ e.Code, e.Family, @@ -343,19 +353,23 @@ type EDNS0_COOKIE struct { Cookie string // Hex-encoded cookie data } -func (e *EDNS0_COOKIE) pack() ([]byte, error) { - h, err := hex.DecodeString(e.Cookie) - if err != nil { - return nil, err - } - return h, nil +func (e *EDNS0_COOKIE) Len() int { + return hex.DecodedLen(len(e.Cookie)) +} + +func (e *EDNS0_COOKIE) Pack(b []byte) (int, error) { + cookie := []byte(e.Cookie) + return hex.Decode(cookie, b) } // Option implements the EDNS0 interface. -func (e *EDNS0_COOKIE) Option() uint16 { return EDNS0COOKIE } -func (e *EDNS0_COOKIE) unpack(b []byte) error { e.Cookie = hex.EncodeToString(b); return nil } -func (e *EDNS0_COOKIE) String() string { return e.Cookie } -func (e *EDNS0_COOKIE) copy() EDNS0 { return &EDNS0_COOKIE{e.Code, e.Cookie} } +func (e *EDNS0_COOKIE) Option() uint16 { return EDNS0COOKIE } +func (e *EDNS0_COOKIE) Unpack(b []byte) (int, error) { + e.Cookie = hex.EncodeToString(b) + return len(b), nil +} +func (e *EDNS0_COOKIE) String() string { return e.Cookie } +func (e *EDNS0_COOKIE) Copy() EDNS0 { return &EDNS0_COOKIE{e.Code, e.Cookie} } // The EDNS0_UL (Update Lease) (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 @@ -378,32 +392,39 @@ type EDNS0_UL struct { // Option implements the EDNS0 interface. func (e *EDNS0_UL) Option() uint16 { return EDNS0UL } func (e *EDNS0_UL) String() string { return fmt.Sprintf("%d %d", e.Lease, e.KeyLease) } -func (e *EDNS0_UL) copy() EDNS0 { return &EDNS0_UL{e.Code, e.Lease, e.KeyLease} } +func (e *EDNS0_UL) Copy() EDNS0 { return &EDNS0_UL{e.Code, e.Lease, e.KeyLease} } -// Copied: http://golang.org/src/pkg/net/dnsmsg.go -func (e *EDNS0_UL) pack() ([]byte, error) { - var b []byte +func (e *EDNS0_UL) Len() int { if e.KeyLease == 0 { - b = make([]byte, 4) - } else { - b = make([]byte, 8) - binary.BigEndian.PutUint32(b[4:], e.KeyLease) + return 4 } - binary.BigEndian.PutUint32(b, e.Lease) - return b, nil + return 8 + } -func (e *EDNS0_UL) unpack(b []byte) error { - switch len(b) { +// Copied: http://golang.org/src/pkg/net/dnsmsg.go +func (e *EDNS0_UL) Pack(b []byte) (int, error) { + l := 4 + if e.KeyLease != 0 { + binary.BigEndian.PutUint32(b[4:], e.KeyLease) + l += 4 + } + binary.BigEndian.PutUint32(b, e.Lease) + return l, nil +} + +func (e *EDNS0_UL) Unpack(b []byte) (int, error) { + l := len(b) + switch l { case 4: e.KeyLease = 0 case 8: e.KeyLease = binary.BigEndian.Uint32(b[4:]) default: - return ErrBuf + return 0, ErrBuf } e.Lease = binary.BigEndian.Uint32(b) - return nil + return l, nil } // EDNS0_LLQ stands for Long Lived Queries: http://tools.ietf.org/html/draft-sekar-dns-llq-01 @@ -420,26 +441,29 @@ type EDNS0_LLQ struct { // Option implements the EDNS0 interface. func (e *EDNS0_LLQ) Option() uint16 { return EDNS0LLQ } -func (e *EDNS0_LLQ) pack() ([]byte, error) { - b := make([]byte, 18) +func (e *EDNS0_LLQ) Len() int { + return 18 +} + +func (e *EDNS0_LLQ) Pack(b []byte) (int, error) { binary.BigEndian.PutUint16(b[0:], e.Version) binary.BigEndian.PutUint16(b[2:], e.Opcode) binary.BigEndian.PutUint16(b[4:], e.Error) binary.BigEndian.PutUint64(b[6:], e.Id) binary.BigEndian.PutUint32(b[14:], e.LeaseLife) - return b, nil + return 18, nil } -func (e *EDNS0_LLQ) unpack(b []byte) error { +func (e *EDNS0_LLQ) Unpack(b []byte) (int, error) { if len(b) < 18 { - return ErrBuf + return 0, ErrBuf } e.Version = binary.BigEndian.Uint16(b[0:]) e.Opcode = binary.BigEndian.Uint16(b[2:]) e.Error = binary.BigEndian.Uint16(b[4:]) e.Id = binary.BigEndian.Uint64(b[6:]) e.LeaseLife = binary.BigEndian.Uint32(b[14:]) - return nil + return 18, nil } func (e *EDNS0_LLQ) String() string { @@ -448,7 +472,7 @@ func (e *EDNS0_LLQ) String() string { " " + strconv.FormatUint(uint64(e.LeaseLife), 10) return s } -func (e *EDNS0_LLQ) copy() EDNS0 { +func (e *EDNS0_LLQ) Copy() EDNS0 { return &EDNS0_LLQ{e.Code, e.Version, e.Opcode, e.Error, e.Id, e.LeaseLife} } @@ -459,9 +483,13 @@ type EDNS0_DAU struct { } // Option implements the EDNS0 interface. -func (e *EDNS0_DAU) Option() uint16 { return EDNS0DAU } -func (e *EDNS0_DAU) pack() ([]byte, error) { return e.AlgCode, nil } -func (e *EDNS0_DAU) unpack(b []byte) error { e.AlgCode = b; return nil } +func (e *EDNS0_DAU) Option() uint16 { return EDNS0DAU } +func (e *EDNS0_DAU) Len() int { return len(e.AlgCode) } +func (e *EDNS0_DAU) Pack(b []byte) (int, error) { return copy(b, e.AlgCode), nil } +func (e *EDNS0_DAU) Unpack(b []byte) (int, error) { + e.AlgCode = make([]byte, len(b)) + return copy(e.AlgCode, b), nil +} func (e *EDNS0_DAU) String() string { s := "" @@ -474,7 +502,7 @@ func (e *EDNS0_DAU) String() string { } return s } -func (e *EDNS0_DAU) copy() EDNS0 { return &EDNS0_DAU{e.Code, e.AlgCode} } +func (e *EDNS0_DAU) Copy() EDNS0 { return &EDNS0_DAU{e.Code, e.AlgCode} } // EDNS0_DHU implements the EDNS0 "DS Hash Understood" option. See RFC 6975. type EDNS0_DHU struct { @@ -483,9 +511,13 @@ type EDNS0_DHU struct { } // Option implements the EDNS0 interface. -func (e *EDNS0_DHU) Option() uint16 { return EDNS0DHU } -func (e *EDNS0_DHU) pack() ([]byte, error) { return e.AlgCode, nil } -func (e *EDNS0_DHU) unpack(b []byte) error { e.AlgCode = b; return nil } +func (e *EDNS0_DHU) Option() uint16 { return EDNS0DHU } +func (e *EDNS0_DHU) Len() int { return len(e.AlgCode) } +func (e *EDNS0_DHU) Pack(b []byte) (int, error) { return copy(b, e.AlgCode), nil } +func (e *EDNS0_DHU) Unpack(b []byte) (int, error) { + e.AlgCode = make([]byte, len(b)) + return copy(e.AlgCode, b), nil +} func (e *EDNS0_DHU) String() string { s := "" @@ -498,7 +530,7 @@ func (e *EDNS0_DHU) String() string { } return s } -func (e *EDNS0_DHU) copy() EDNS0 { return &EDNS0_DHU{e.Code, e.AlgCode} } +func (e *EDNS0_DHU) Copy() EDNS0 { return &EDNS0_DHU{e.Code, e.AlgCode} } // EDNS0_N3U implements the EDNS0 "NSEC3 Hash Understood" option. See RFC 6975. type EDNS0_N3U struct { @@ -507,9 +539,13 @@ type EDNS0_N3U struct { } // Option implements the EDNS0 interface. -func (e *EDNS0_N3U) Option() uint16 { return EDNS0N3U } -func (e *EDNS0_N3U) pack() ([]byte, error) { return e.AlgCode, nil } -func (e *EDNS0_N3U) unpack(b []byte) error { e.AlgCode = b; return nil } +func (e *EDNS0_N3U) Option() uint16 { return EDNS0N3U } +func (e *EDNS0_N3U) Len() int { return len(e.AlgCode) } +func (e *EDNS0_N3U) Pack(b []byte) (int, error) { return copy(b, e.AlgCode), nil } +func (e *EDNS0_N3U) Unpack(b []byte) (int, error) { + e.AlgCode = make([]byte, len(b)) + return copy(e.AlgCode, b), nil +} func (e *EDNS0_N3U) String() string { // Re-use the hash map @@ -523,7 +559,7 @@ func (e *EDNS0_N3U) String() string { } return s } -func (e *EDNS0_N3U) copy() EDNS0 { return &EDNS0_N3U{e.Code, e.AlgCode} } +func (e *EDNS0_N3U) Copy() EDNS0 { return &EDNS0_N3U{e.Code, e.AlgCode} } // EDNS0_EXPIRE implementes the EDNS0 option as described in RFC 7314. type EDNS0_EXPIRE struct { @@ -534,20 +570,26 @@ type EDNS0_EXPIRE struct { // 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) 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 +func (e *EDNS0_EXPIRE) Len() int { + return 4 } -func (e *EDNS0_EXPIRE) unpack(b []byte) error { +func (e *EDNS0_EXPIRE) Pack(b []byte) (int, error) { if len(b) < 4 { - return ErrBuf + return 0, ErrBuf + } + binary.BigEndian.PutUint32(b, e.Expire) + return 4, nil +} + +func (e *EDNS0_EXPIRE) Unpack(b []byte) (int, error) { + if len(b) < 4 { + return 0, ErrBuf } e.Expire = binary.BigEndian.Uint32(b) - return nil + return 4, nil } // The EDNS0_LOCAL option is used for local/experimental purposes. The option @@ -573,28 +615,31 @@ func (e *EDNS0_LOCAL) Option() uint16 { return e.Code } func (e *EDNS0_LOCAL) String() string { return strconv.FormatInt(int64(e.Code), 10) + ":0x" + hex.EncodeToString(e.Data) } -func (e *EDNS0_LOCAL) copy() EDNS0 { +func (e *EDNS0_LOCAL) Copy() EDNS0 { b := make([]byte, len(e.Data)) copy(b, e.Data) return &EDNS0_LOCAL{e.Code, b} } -func (e *EDNS0_LOCAL) pack() ([]byte, error) { - b := make([]byte, len(e.Data)) - copied := copy(b, e.Data) - if copied != len(e.Data) { - return nil, ErrBuf - } - return b, nil +func (e *EDNS0_LOCAL) Len() int { + return len(e.Data) } -func (e *EDNS0_LOCAL) unpack(b []byte) error { +func (e *EDNS0_LOCAL) Pack(b []byte) (int, error) { + copied := copy(b, e.Data) + if copied != len(e.Data) { + return 0, ErrBuf + } + return copied, nil +} + +func (e *EDNS0_LOCAL) Unpack(b []byte) (int, error) { e.Data = make([]byte, len(b)) copied := copy(e.Data, b) if copied != len(b) { - return ErrBuf + return 0, ErrBuf } - return nil + return copied, nil } // EDNS0_TCP_KEEPALIVE is an EDNS0 option that instructs the server to keep @@ -608,37 +653,40 @@ type EDNS0_TCP_KEEPALIVE struct { // Option implements the EDNS0 interface. func (e *EDNS0_TCP_KEEPALIVE) Option() uint16 { return EDNS0TCPKEEPALIVE } -func (e *EDNS0_TCP_KEEPALIVE) pack() ([]byte, error) { +func (e *EDNS0_TCP_KEEPALIVE) Len() int { + return int(4 + e.Length) +} + +func (e *EDNS0_TCP_KEEPALIVE) Pack(b []byte) (int, error) { if e.Timeout != 0 && e.Length != 2 { - return nil, errors.New("dns: timeout specified but length is not 2") + return 0, errors.New("dns: timeout specified but length is not 2") } if e.Timeout == 0 && e.Length != 0 { - return nil, errors.New("dns: timeout not specified but length is not 0") + return 0, errors.New("dns: timeout not specified but length is not 0") } - b := make([]byte, 4+e.Length) binary.BigEndian.PutUint16(b[0:], e.Code) binary.BigEndian.PutUint16(b[2:], e.Length) if e.Length == 2 { binary.BigEndian.PutUint16(b[4:], e.Timeout) } - return b, nil + return e.Len(), nil } -func (e *EDNS0_TCP_KEEPALIVE) unpack(b []byte) error { +func (e *EDNS0_TCP_KEEPALIVE) Unpack(b []byte) (int, error) { if len(b) < 4 { - return ErrBuf + return 0, ErrBuf } e.Length = binary.BigEndian.Uint16(b[2:4]) if e.Length != 0 && e.Length != 2 { - return errors.New("dns: length mismatch, want 0/2 but got " + strconv.FormatUint(uint64(e.Length), 10)) + return 0, errors.New("dns: length mismatch, want 0/2 but got " + strconv.FormatUint(uint64(e.Length), 10)) } if e.Length == 2 { if len(b) < 6 { - return ErrBuf + return 0, ErrBuf } e.Timeout = binary.BigEndian.Uint16(b[4:6]) } - return nil + return e.Len(), nil } func (e *EDNS0_TCP_KEEPALIVE) String() (s string) { @@ -650,7 +698,7 @@ func (e *EDNS0_TCP_KEEPALIVE) String() (s string) { } return } -func (e *EDNS0_TCP_KEEPALIVE) copy() EDNS0 { return &EDNS0_TCP_KEEPALIVE{e.Code, e.Length, e.Timeout} } +func (e *EDNS0_TCP_KEEPALIVE) Copy() EDNS0 { return &EDNS0_TCP_KEEPALIVE{e.Code, e.Length, e.Timeout} } // EDNS0_PADDING option is used to add padding to a request/response. The default // value of padding SHOULD be 0x0 but other values MAY be used, for instance if @@ -660,11 +708,15 @@ type EDNS0_PADDING struct { } // Option implements the EDNS0 interface. -func (e *EDNS0_PADDING) Option() uint16 { return EDNS0PADDING } -func (e *EDNS0_PADDING) pack() ([]byte, error) { return e.Padding, nil } -func (e *EDNS0_PADDING) unpack(b []byte) error { e.Padding = b; return nil } -func (e *EDNS0_PADDING) String() string { return fmt.Sprintf("%0X", e.Padding) } -func (e *EDNS0_PADDING) copy() EDNS0 { +func (e *EDNS0_PADDING) Option() uint16 { return EDNS0PADDING } +func (e *EDNS0_PADDING) Len() int { return len(e.Padding) } +func (e *EDNS0_PADDING) Pack(b []byte) (int, error) { return copy(b, e.Padding), nil } +func (e *EDNS0_PADDING) Unpack(b []byte) (int, error) { + e.Padding = make([]byte, len(b)) + return copy(e.Padding, b), nil +} +func (e *EDNS0_PADDING) String() string { return fmt.Sprintf("%0X", e.Padding) } +func (e *EDNS0_PADDING) Copy() EDNS0 { b := make([]byte, len(e.Padding)) copy(b, e.Padding) return &EDNS0_PADDING{b} diff --git a/edns_test.go b/edns_test.go index d18961ed..e8bfc8c9 100644 --- a/edns_test.go +++ b/edns_test.go @@ -94,13 +94,14 @@ func TestEDNS0_SUBNETUnpack(t *testing.T) { s1.SourceNetmask = net.IPv4len * 8 } - b, err := s1.pack() + b := make([]byte, s1.Len()) + _, err := s1.Pack(b) if err != nil { t.Fatalf("failed to pack: %v", err) } var s2 EDNS0_SUBNET - if err := s2.unpack(b); err != nil { + if _, err := s2.Unpack(b); err != nil { t.Fatalf("failed to unpack: %v", err) } @@ -120,12 +121,13 @@ func TestEDNS0_UL(t *testing.T) { } for _, c := range cases { expect := EDNS0_UL{EDNS0UL, c.l, c.kl} - b, err := expect.pack() + b := make([]byte, expect.Len()) + _, err := expect.Pack(b) if err != nil { t.Fatalf("failed to pack: %v", err) } actual := EDNS0_UL{EDNS0UL, ^uint32(0), ^uint32(0)} - if err := actual.unpack(b); err != nil { + if _, err := actual.Unpack(b); err != nil { t.Fatalf("failed to unpack: %v", err) } if expect != actual { diff --git a/msg_helpers.go b/msg_helpers.go index 0e96f0f3..19746ecc 100644 --- a/msg_helpers.go +++ b/msg_helpers.go @@ -426,63 +426,63 @@ Option: switch code { case EDNS0NSID: e := new(EDNS0_NSID) - if err := e.unpack(msg[off : off+int(optlen)]); err != nil { + if _, err := e.Unpack(msg[off : off+int(optlen)]); err != nil { return nil, len(msg), err } edns = append(edns, e) off += int(optlen) case EDNS0SUBNET: e := new(EDNS0_SUBNET) - if err := e.unpack(msg[off : off+int(optlen)]); err != nil { + if _, err := e.Unpack(msg[off : off+int(optlen)]); err != nil { return nil, len(msg), err } edns = append(edns, e) off += int(optlen) case EDNS0COOKIE: e := new(EDNS0_COOKIE) - if err := e.unpack(msg[off : off+int(optlen)]); err != nil { + if _, err := e.Unpack(msg[off : off+int(optlen)]); err != nil { return nil, len(msg), err } edns = append(edns, e) off += int(optlen) case EDNS0UL: e := new(EDNS0_UL) - if err := e.unpack(msg[off : off+int(optlen)]); err != nil { + if _, err := e.Unpack(msg[off : off+int(optlen)]); err != nil { return nil, len(msg), err } edns = append(edns, e) off += int(optlen) case EDNS0LLQ: e := new(EDNS0_LLQ) - if err := e.unpack(msg[off : off+int(optlen)]); err != nil { + if _, err := e.Unpack(msg[off : off+int(optlen)]); err != nil { return nil, len(msg), err } edns = append(edns, e) off += int(optlen) case EDNS0DAU: e := new(EDNS0_DAU) - if err := e.unpack(msg[off : off+int(optlen)]); err != nil { + if _, err := e.Unpack(msg[off : off+int(optlen)]); err != nil { return nil, len(msg), err } edns = append(edns, e) off += int(optlen) case EDNS0DHU: e := new(EDNS0_DHU) - if err := e.unpack(msg[off : off+int(optlen)]); err != nil { + if _, err := e.Unpack(msg[off : off+int(optlen)]); err != nil { return nil, len(msg), err } edns = append(edns, e) off += int(optlen) case EDNS0N3U: e := new(EDNS0_N3U) - if err := e.unpack(msg[off : off+int(optlen)]); err != nil { + if _, err := e.Unpack(msg[off : off+int(optlen)]); err != nil { return nil, len(msg), err } edns = append(edns, e) off += int(optlen) case EDNS0PADDING: e := new(EDNS0_PADDING) - if err := e.unpack(msg[off : off+int(optlen)]); err != nil { + if _, err := e.Unpack(msg[off : off+int(optlen)]); err != nil { return nil, len(msg), err } edns = append(edns, e) @@ -490,7 +490,7 @@ Option: default: e := new(EDNS0_LOCAL) e.Code = code - if err := e.unpack(msg[off : off+int(optlen)]); err != nil { + if _, err := e.Unpack(msg[off : off+int(optlen)]); err != nil { return nil, len(msg), err } edns = append(edns, e) @@ -506,7 +506,8 @@ Option: func packDataOpt(options []EDNS0, msg []byte, off int) (int, error) { for _, el := range options { - b, err := el.pack() + b := make([]byte, el.Len()) + _, err := el.Pack(b) if err != nil || off+4 > len(msg) { return len(msg), &Error{err: "overflow packing opt"} } diff --git a/ztypes.go b/ztypes.go index f7ec8352..4060788b 100644 --- a/ztypes.go +++ b/ztypes.go @@ -805,7 +805,7 @@ func (rr *OPENPGPKEY) copy() RR { func (rr *OPT) copy() RR { Option := make([]EDNS0, len(rr.Option)) for i, e := range rr.Option { - Option[i] = e.copy() + Option[i] = e.Copy() } return &OPT{rr.Hdr, Option} }