123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- // Copyright 2022 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #ifndef NET_DNS_OPT_RECORD_RDATA_H_
- #define NET_DNS_OPT_RECORD_RDATA_H_
- #include <stdint.h>
- #include <map>
- #include <memory>
- #include <string>
- #include <vector>
- #include "base/strings/string_piece.h"
- #include "net/base/net_export.h"
- #include "net/dns/public/dns_protocol.h"
- #include "net/dns/record_rdata.h"
- namespace net {
- // OPT record format (https://tools.ietf.org/html/rfc6891):
- class NET_EXPORT_PRIVATE OptRecordRdata : public RecordRdata {
- public:
- static std::unique_ptr<OptRecordRdata> Create(base::StringPiece data);
- class NET_EXPORT_PRIVATE Opt {
- public:
- static constexpr size_t kHeaderSize = 4; // sizeof(code) + sizeof(size)
- Opt() = delete;
- explicit Opt(std::string data);
- Opt(const Opt& other) = delete;
- Opt& operator=(const Opt& other) = delete;
- Opt(Opt&& other) = delete;
- Opt& operator=(Opt&& other) = delete;
- virtual ~Opt() = default;
- bool operator==(const Opt& other) const;
- bool operator!=(const Opt& other) const;
- virtual uint16_t GetCode() const = 0;
- base::StringPiece data() const { return data_; }
- private:
- bool IsEqual(const Opt& other) const;
- std::string data_;
- };
- class NET_EXPORT_PRIVATE EdeOpt : public Opt {
- public:
- static const uint16_t kOptCode = dns_protocol::kEdnsExtendedDnsError;
- // The following errors are defined by in the IANA registry.
- // https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#extended-dns-error-codes
- enum EdeInfoCode {
- kOtherError,
- kUnsupportedDnskeyAlgorithm,
- kUnsupportedDsDigestType,
- kStaleAnswer,
- kForgedAnswer,
- kDnssecIndeterminate,
- kDnssecBogus,
- kSignatureExpired,
- kSignatureNotYetValid,
- kDnskeyMissing,
- kRrsigsMissing,
- kNoZoneKeyBitSet,
- kNsecMissing,
- kCachedError,
- kNotReady,
- kBlocked,
- kCensored,
- kFiltered,
- kProhibited,
- kStaleNxdomainAnswer,
- kNotAuthoritative,
- kNotSupported,
- kNoReachableAuthority,
- kNetworkError,
- kInvalidData,
- kSignatureExpiredBeforeValid,
- kTooEarly,
- kUnsupportedNsec3IterationsValue,
- // Note: kUnrecognizedErrorCode is not defined by RFC 8914.
- // Used when error code does not match existing RFC error code.
- kUnrecognizedErrorCode
- };
- EdeOpt(uint16_t info_code, std::string extra_text);
- EdeOpt(const EdeOpt& other) = delete;
- EdeOpt& operator=(const EdeOpt& other) = delete;
- EdeOpt(EdeOpt&& other) = delete;
- EdeOpt& operator=(EdeOpt&& other) = delete;
- ~EdeOpt() override;
- // Attempts to parse an EDE option from `data`. Returns nullptr on failure.
- static std::unique_ptr<EdeOpt> Create(std::string data);
- uint16_t GetCode() const override;
- uint16_t info_code() const { return info_code_; }
- base::StringPiece extra_text() const { return extra_text_; }
- EdeInfoCode GetEnumFromInfoCode() const;
- // Convert a uint16_t to an EdeInfoCode enum.
- static EdeInfoCode GetEnumFromInfoCode(uint16_t info_code);
- private:
- EdeOpt();
- uint16_t info_code_;
- std::string extra_text_;
- };
- class NET_EXPORT_PRIVATE PaddingOpt : public Opt {
- public:
- static const uint16_t kOptCode = dns_protocol::kEdnsPadding;
- PaddingOpt() = delete;
- // Construct a PaddingOpt with the specified padding string.
- explicit PaddingOpt(std::string padding);
- // Constructs PaddingOpt with '\0' character padding of specified length.
- // Note: This padding_len only specifies the length of the data section.
- // Users must take into account the header length `Opt::kHeaderSize`
- explicit PaddingOpt(uint16_t padding_len);
- PaddingOpt(const PaddingOpt& other) = delete;
- PaddingOpt& operator=(const PaddingOpt& other) = delete;
- PaddingOpt(PaddingOpt&& other) = delete;
- PaddingOpt& operator=(PaddingOpt&& other) = delete;
- ~PaddingOpt() override;
- uint16_t GetCode() const override;
- };
- class NET_EXPORT_PRIVATE UnknownOpt : public Opt {
- public:
- UnknownOpt() = delete;
- UnknownOpt(const UnknownOpt& other) = delete;
- UnknownOpt& operator=(const UnknownOpt& other) = delete;
- UnknownOpt(UnknownOpt&& other) = delete;
- UnknownOpt& operator=(UnknownOpt&& other) = delete;
- ~UnknownOpt() override;
- // Create UnknownOpt with option code and data.
- // Cannot instantiate UnknownOpt directly in order to prevent Opt with
- // dedicated class class (ex. EdeOpt) from being stored in UnknownOpt.
- // object.
- // This method must purely be used for testing.
- // Only the parser can instantiate an UnknownOpt object (via friend
- // classes).
- static std::unique_ptr<UnknownOpt> CreateForTesting(uint16_t code,
- std::string data);
- uint16_t GetCode() const override;
- private:
- UnknownOpt(uint16_t code, std::string data);
- uint16_t code_;
- friend std::unique_ptr<OptRecordRdata> OptRecordRdata::Create(
- base::StringPiece data);
- };
- static constexpr uint16_t kOptsWithDedicatedClasses[] = {
- dns_protocol::kEdnsPadding, dns_protocol::kEdnsExtendedDnsError};
- static const uint16_t kType = dns_protocol::kTypeOPT;
- OptRecordRdata();
- OptRecordRdata(const OptRecordRdata&) = delete;
- OptRecordRdata& operator=(const OptRecordRdata&) = delete;
- OptRecordRdata(OptRecordRdata&& other) = delete;
- OptRecordRdata& operator=(OptRecordRdata&& other) = delete;
- ~OptRecordRdata() override;
- bool operator==(const OptRecordRdata& other) const;
- bool operator!=(const OptRecordRdata& other) const;
- // Checks whether two OptRecordRdata objects are equal. This comparison takes
- // into account the order of insertion. Two OptRecordRdata objects with
- // identical Opt records inserted in a different order will not be equal.
- bool IsEqual(const RecordRdata* other) const override;
- uint16_t Type() const override;
- const std::vector<char>& buf() const { return buf_; }
- const std::multimap<uint16_t, const std::unique_ptr<const Opt>>& opts()
- const {
- return opts_;
- }
- // Add specified Opt to rdata. Updates raw buffer as well.
- void AddOpt(const std::unique_ptr<Opt> opt);
- // Checks if an Opt with the specified opt_code is contained.
- bool ContainsOptCode(uint16_t opt_code) const;
- size_t OptCount() const { return opts_.size(); }
- // Returns all options sorted by option code, using insertion order to break
- // ties.
- std::vector<const Opt*> GetOpts() const;
- // Returns all EDE options in insertion order.
- std::vector<const EdeOpt*> GetEdeOpts() const;
- // Returns all Padding options in insertion order.
- std::vector<const PaddingOpt*> GetPaddingOpts() const;
- private:
- // Opt objects are stored in a multimap; key is the opt code.
- std::multimap<uint16_t, const std::unique_ptr<const Opt>> opts_;
- std::vector<char> buf_;
- };
- } // namespace net
- #endif // NET_DNS_OPT_RECORD_RDATA_H_
|