• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PowerDNS / pdns / 12595591960

03 Jan 2025 09:27AM UTC coverage: 62.774% (+2.5%) from 60.245%
12595591960

Pull #15008

github

web-flow
Merge c2a2749d3 into 788f396a7
Pull Request #15008: Do not follow CNAME records for ANY or CNAME queries

30393 of 78644 branches covered (38.65%)

Branch coverage included in aggregate %.

105822 of 138350 relevant lines covered (76.49%)

4613078.44 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

47.06
/pdns/dnspacket.hh
1
/*
2
 * This file is part of PowerDNS or dnsdist.
3
 * Copyright -- PowerDNS.COM B.V. and its contributors
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of version 2 of the GNU General Public License as
7
 * published by the Free Software Foundation.
8
 *
9
 * In addition, for the avoidance of any doubt, permission is granted to
10
 * link this program with OpenSSL and to (re)distribute the binaries
11
 * produced as the result of such linking.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
 */
22
#pragma once
23
#include <sys/types.h>
24
#include "iputils.hh"
25
#include "ednssubnet.hh"
26
#include "ednscookies.hh"
27
#include <optional>
28
#include <unordered_set>
29
#include <sys/socket.h>
30
#include <netinet/in.h>
31
#include <sys/time.h>
32
#include <unistd.h>
33
#include <arpa/inet.h>
34

35
#include <iostream>
36
#include <optional>
37
#include <string>
38
#include <vector>
39
#include "qtype.hh"
40
#include "dns.hh"
41
#include "misc.hh"
42
#include "utility.hh"
43
#include "logger.hh"
44
#include "pdnsexception.hh"
45
#include "dnsrecords.hh"
46

47

48
//! This class represents DNS packets, either received or to be sent.
49
class DNSPacket
50
{
51
public:
52
  DNSPacket(bool isQuery);
53
  DNSPacket(const DNSPacket &orig) = default;
54
  DNSPacket & operator=(const DNSPacket &) = default;
55

56
  int noparse(const char *mesg, size_t len); //!< just suck the data inward
57
  int parse(const char *mesg, size_t len); //!< parse a raw UDP or TCP packet and suck the data inward
58
  const string& getString(bool throwsOnTruncation=false); //!< for serialization - just passes the whole packet. If throwsOnTruncation is set, an exception will be raised if the records are too large to fit inside a single DNS payload, instead of setting the TC bit
59

60
  // address & socket manipulation
61
  void setRemote(const ComboAddress*, std::optional<ComboAddress> = std::nullopt);
62
  ComboAddress getRemote() const;
63
  ComboAddress getInnerRemote() const; // for proxy protocol
64
  Netmask getRealRemote() const;
65
  void setRealRemote(const Netmask& netmask);
66
  ComboAddress getLocal() const
67
  {
3✔
68
    ComboAddress ca;
3✔
69
    socklen_t len=sizeof(ca);
3✔
70
    getsockname(d_socket, (sockaddr*)&ca, &len);
3✔
71
    return ca;
3✔
72
  }
3✔
73
  uint16_t getRemotePort() const;
74

75
  string getRemoteString() const;
76
  string getRemoteStringWithPort() const;
77

78
  boost::optional<ComboAddress> d_anyLocal;
79

80
  Utility::sock_t getSocket() const
81
  {
×
82
    return d_socket;
×
83
  }
×
84
  void setSocket(Utility::sock_t sock);
85

86
  // these manipulate 'd'
87
  void setA(bool); //!< make this packet authoritative - manipulates 'd'
88
  void setID(uint16_t); //!< set the DNS id of this packet - manipulates 'd'
89
  void setRA(bool); //!< set the Recursion Available flag - manipulates 'd'
90
  void setRD(bool); //!< set the Recursion Desired flag - manipulates 'd'
91
  void setAnswer(bool); //!< Make this packet an answer - clears the 'stringbuffer' first, if passed 'true', does nothing otherwise, manipulates 'd'
92

93
  void setOpcode(uint16_t);  //!< set the Opcode of this packet - manipulates 'd'
94
  void setRcode(int v); //!< set the Rcode of this packet - manipulates 'd'
95

96
  void clearRecords(); //!< when building a packet, wipe all previously added records (clears 'rrs')
97

98
  /** Add a DNSZoneRecord to this packet. A DNSPacket (as does a DNS Packet) has 4 kinds of resource records. Questions,
99
      Answers, Authority and Additional. See RFC 1034 and 1035 for details. You can specify where a record needs to go in the
100
      DNSZoneRecord d_place field */
101
  void addRecord(DNSZoneRecord&&);  // adds to 'rrs'
102

103
  void setQuestion(int op, const DNSName &qdomain, int qtype);  // wipes 'd', sets a random id, creates start of packet (domain, type, class etc)
104

105
  DTime d_dt; //!< the time this packet was created. replyPacket() copies this in for you, so d_dt becomes the time spent processing the question+answer
106
  void wrapup(bool throwsOnTruncation=false);  // writes out queued rrs, and generates the binary packet. also shuffles. also rectifies dnsheader 'd', and copies it to the stringbuffer. If throwsOnTruncation is set, an exception will be raised if the records are too large to fit inside a single DNS payload, instead of setting the TC bit
107
  void spoofQuestion(const DNSPacket& qd); //!< paste in the exact right case of the question. Useful for PacketCache
108
  unsigned int getMinTTL(); //!< returns lowest TTL of any record in the packet
109
  bool isEmpty(); //!< returns true if there are no rrs in the packet
110

111
  vector<DNSZoneRecord*> getAPRecords(); //!< get a vector with DNSZoneRecords that need additional processing
112
  vector<DNSZoneRecord*> getAnswerRecords(); //!< get a vector with DNSZoneRecords that are answers
113
  vector<DNSZoneRecord*> getServiceRecords(); //!< Get a vector with all Service-style (SVCB) records
114
  void setCompress(bool compress);
115

116
  std::unique_ptr<DNSPacket> replyPacket() const; //!< convenience function that creates a virgin answer packet to this question
117

118
  void commitD(); //!< copies 'd' into the stringbuffer
119
  unsigned int getMaxReplyLen(); //!< retrieve the maximum length of the packet we should send in response
120
  void setMaxReplyLen(int bytes); //!< set the max reply len (used when retrieving from the packet cache, and this changed)
121

122
  bool couldBeCached() const; //!< returns 0 if this query should bypass the packet cache
123
  bool hasEDNSSubnet() const;
124
  bool hasEDNS() const;
125
  bool hasEDNSCookie() const;
126
  bool hasWellFormedEDNSCookie() const;
127
  bool hasValidEDNSCookie() const;
128
  uint8_t getEDNSVersion() const { return d_ednsversion; };
×
129
  void setEDNSRcode(uint16_t extRCode)
130
  {
×
131
    // WARNING: this is really 12 bits
132
    d_ednsrcode=extRCode;
×
133
  };
×
134
  uint8_t getEDNSRCode() const { return d_ednsrcode; };
×
135
  uint32_t getHash() const { return d_hash; };
395,716✔
136
  void setHash(uint32_t hash) { d_hash = hash; };
793,537✔
137

138
  //////// DATA !
139

140
  DNSName qdomain;  //!< qname of the question 4 - unsure how this is used
141
  DNSName qdomainwild;  //!< wildcard matched by qname, used by LuaPolicyEngine
142
  DNSName qdomainzone;  //!< zone name for the answer (as reflected in SOA for negative responses), used by LuaPolicyEngine
143
  string d_peer_principal;
144
  const DNSName& getTSIGKeyname() const;
145

146
  struct dnsheader d; //!< dnsheader at the start of the databuffer 12
147

148
  TSIGRecordContent d_trc; //72
149

150
  ComboAddress d_remote; //28
151
  std::optional<ComboAddress> d_inner_remote; // the 'outer' remote is the IP on the physical packet header. The 'inner' remote lives one layer deeper, in the PROXY header.
152
  TSIGHashEnum d_tsig_algo{TSIG_MD5}; //4
153

154
  int d_ednsRawPacketSizeLimit{-1}; // only used for Lua record
155
  uint16_t qclass{QClass::IN};  //!< class of the question - should always be INternet 2
156
  QType qtype;  //!< type of the question 2
157

158
  bool d_tcp{false}; // whether DNS packet is using TCP (false when UDP)
159
  bool d_xfr{false}; // whether DNS packet is a zone transfer, either AXFR or IXFR
160
  bool d_dnssecOk{false};
161
  bool d_havetsig{false};
162

163
  bool getTSIGDetails(TSIGRecordContent* tr, DNSName* keyname, uint16_t* tsigPos=nullptr) const;
164
  void setTSIGDetails(const TSIGRecordContent& tr, const DNSName& keyname, const string& secret, const string& previous, bool timersonly=false);
165
  bool validateTSIG(const TSIGTriplet& tsigTriplet, const TSIGRecordContent& tsigContent, const std::string& previousMAC, const std::string& theirMAC, bool timersOnly) const;
166
  bool getTKEYRecord(TKEYRecordContent* tr, DNSName* keyname) const;
167

168
  vector<DNSZoneRecord>& getRRS() { return d_rrs; }
×
169

170
  static uint16_t s_udpTruncationThreshold;
171
  static bool s_doEDNSSubnetProcessing;
172
  static bool s_doEDNSCookieProcessing;
173
  static string s_EDNSCookieKey;
174
  EDNSSubnetOpts d_eso;
175

176
#ifdef ENABLE_GSS_TSIG
177
  void cleanupGSS(int rcode);
178
#endif
179

180
private:
181
  void pasteQ(const char *question, int length); //!< set the question of this packet, useful for crafting replies
182

183
  string d_tsigsecret;
184
  DNSName d_tsigkeyname;
185
  string d_tsigprevious;
186

187
  vector<DNSZoneRecord> d_rrs; // 8
188
  std::unordered_set<size_t> d_dedup;
189
  string d_rawpacket; // this is where everything lives 8
190
  EDNSCookiesOpt d_eco;
191

192
  int d_maxreplylen{0};
193
  int d_socket{-1}; // 4
194
  uint32_t d_hash{0};
195
  // WARNING! This is really 12 bits
196
  uint16_t d_ednsrcode{0};
197
  uint8_t d_ednsversion{0};
198

199
  bool d_wrapped{false}; // 1
200
  bool d_compress{true}; // 1
201
  bool d_tsigtimersonly{false};
202
  bool d_wantsnsid{false};
203
  bool d_haveednssubnet{false};
204
  bool d_haveednscookie{false};
205
  bool d_ednscookievalid{false};
206
  bool d_haveednssection{false};
207
  bool d_isQuery;
208
};
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc