• 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

76.13
/pdns/ednsoptions.cc
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
#include "dns.hh"
23
#include "ednsoptions.hh"
24
#include "iputils.hh"
25

26
bool getNextEDNSOption(const char* data, size_t dataLen, uint16_t& optionCode, uint16_t& optionLen)
27
{
332✔
28
  if (data == nullptr || dataLen < (sizeof(uint16_t) + sizeof(uint16_t))) {
332!
29
    return false;
×
30
  }
×
31

32
  size_t pos = 0;
332✔
33
  const uint8_t* p = reinterpret_cast<const uint8_t*>(data);
332✔
34

35
  optionCode = (static_cast<uint16_t>(p[pos]) * 256) + p[pos + 1];
332✔
36
  pos += EDNS_OPTION_CODE_SIZE;
332✔
37

38
  optionLen = (static_cast<uint16_t>(p[pos]) * 256) + p[pos + 1];
332✔
39
  pos += EDNS_OPTION_LENGTH_SIZE;
332✔
40
  (void) pos;
332✔
41

42
  return true;
332✔
43
}
332✔
44

45
/* extract the position (relative to the optRR pointer!) and size of a specific EDNS0 option from a pointer on the beginning rdLen of the OPT RR */
46
int getEDNSOption(const char* optRR, const size_t len, uint16_t wantedOption, size_t* optionValuePosition, size_t * optionValueSize)
47
{
116✔
48
  if (optRR == nullptr || optionValuePosition == nullptr || optionValueSize == nullptr) {
116!
49
    return EINVAL;
×
50
  }
×
51

52
  size_t pos = 0;
116✔
53
  if (len < DNS_RDLENGTH_SIZE) {
116!
54
    return EINVAL;
×
55
  }
×
56

57
  const uint16_t rdLen = (((unsigned char) optRR[pos]) * 256) + ((unsigned char) optRR[pos+1]);
116✔
58
  size_t rdPos = 0;
116✔
59
  pos += DNS_RDLENGTH_SIZE;
116✔
60
  if ((pos + rdLen) > len) {
116!
61
    return EINVAL;
×
62
  }
×
63

64
  while(len >= (pos + EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE) &&
125✔
65
        rdLen >= (rdPos + EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE)) {
125✔
66
    uint16_t optionCode;
87✔
67
    uint16_t optionLen;
87✔
68
    if (!getNextEDNSOption(optRR + pos, len-pos, optionCode, optionLen)) {
87!
69
      break;
×
70
    }
×
71

72
    pos += EDNS_OPTION_CODE_SIZE;
87✔
73
    rdPos += EDNS_OPTION_CODE_SIZE;
87✔
74
    pos += EDNS_OPTION_LENGTH_SIZE;
87✔
75
    rdPos += EDNS_OPTION_LENGTH_SIZE;
87✔
76

77
    if (optionLen > (rdLen - rdPos) || optionLen > (len - pos)) {
87!
78
      return EINVAL;
×
79
    }
×
80

81
    if (optionCode == wantedOption) {
87✔
82
      *optionValuePosition = pos - (EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE);
78✔
83
      *optionValueSize = optionLen + EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE;
78✔
84
      return 0;
78✔
85
    }
78✔
86
    else {
9✔
87
      /* skip this option */
88
      pos += optionLen;
9✔
89
      rdPos += optionLen;
9✔
90
    }
9✔
91
  }
87✔
92

93
  return ENOENT;
38✔
94
}
116✔
95

96
/* extract all EDNS0 options from a pointer on the beginning rdLen of the OPT RR */
97
int getEDNSOptions(const char* optRR, const size_t len, EDNSOptionViewMap& options)
98
{
84✔
99
  size_t pos = 0;
84✔
100
  if (optRR == nullptr || len < DNS_RDLENGTH_SIZE) {
84!
101
    return EINVAL;
×
102
  }
×
103

104
  const uint16_t rdLen = (((unsigned char) optRR[pos]) * 256) + ((unsigned char) optRR[pos+1]);
84✔
105
  size_t rdPos = 0;
84✔
106
  pos += DNS_RDLENGTH_SIZE;
84✔
107
  if ((pos + rdLen) > len) {
84!
108
    return EINVAL;
×
109
  }
×
110

111
  while(len >= (pos + EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE) &&
190✔
112
        rdLen >= (rdPos + EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE)) {
190✔
113
    const uint16_t optionCode = (((unsigned char) optRR[pos]) * 256) + ((unsigned char) optRR[pos+1]);
106✔
114
    pos += EDNS_OPTION_CODE_SIZE;
106✔
115
    rdPos += EDNS_OPTION_CODE_SIZE;
106✔
116
    const uint16_t optionLen = (((unsigned char) optRR[pos]) * 256) + ((unsigned char) optRR[pos+1]);
106✔
117
    pos += EDNS_OPTION_LENGTH_SIZE;
106✔
118
    rdPos += EDNS_OPTION_LENGTH_SIZE;
106✔
119
    if (optionLen > (rdLen - rdPos) || optionLen > (len - pos))
106!
120
      return EINVAL;
×
121

122
    EDNSOptionViewValue value;
106✔
123
    value.content = optRR + pos;
106✔
124
    value.size = optionLen;
106✔
125
    options[optionCode].values.push_back(value);
106✔
126

127
    /* skip this option */
128
    pos += optionLen;
106✔
129
    rdPos += optionLen;
106✔
130
  }
106✔
131

132
  return 0;
84✔
133
}
84✔
134

135
bool getEDNSOptionsFromContent(const std::string& content, std::vector<std::pair<uint16_t, std::string>>& options)
136
{
44✔
137
  size_t pos = 0;
44✔
138
  uint16_t code, len;
44✔
139
  const size_t contentLength = content.size();
44✔
140

141
  while (pos < contentLength && (contentLength - pos) >= (EDNS_OPTION_CODE_SIZE + EDNS_OPTION_LENGTH_SIZE)) {
84!
142
    code = (static_cast<unsigned char>(content.at(pos)) * 256) + static_cast<unsigned char>(content.at(pos+1));
40✔
143
    pos += EDNS_OPTION_CODE_SIZE;
40✔
144
    len = (static_cast<unsigned char>(content.at(pos)) * 256) + static_cast<unsigned char>(content.at(pos+1));
40✔
145
    pos += EDNS_OPTION_LENGTH_SIZE;
40✔
146

147
    if (pos > contentLength || len > (contentLength - pos)) {
40!
148
      return false;
×
149
    }
×
150

151
    options.emplace_back(code, std::string(&content.at(pos), len));
40✔
152
    pos += len;
40✔
153
  }
40✔
154

155
  return true;
44✔
156
}
44✔
157

158
void generateEDNSOption(uint16_t optionCode, const std::string& payload, std::string& res)
159
{
218✔
160
  const uint16_t ednsOptionCode = htons(optionCode);
218✔
161
  const uint16_t payloadLen = htons(payload.length());
218✔
162
  res.append((const char *) &ednsOptionCode, sizeof ednsOptionCode);
218✔
163
  res.append((const char *) &payloadLen, sizeof payloadLen);
218✔
164
  res.append(payload);
218✔
165
}
218✔
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