• 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

39.71
/pdns/shuffle.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
#ifdef HAVE_CONFIG_H
23
#include "config.h"
24
#endif
25

26
#include <string>
27

28
#include "shuffle.hh"
29
#include "dns_random.hh"
30
#include "dnsparser.hh"
31

32
// shuffle, maintaining some semblance of order
33
void pdns::shuffle(std::vector<DNSZoneRecord>& rrs)
34
{
×
35
  std::vector<DNSZoneRecord>::iterator first;
×
36
  std::vector<DNSZoneRecord>::iterator second;
×
37

38
  // We assume the CNAMES are listed first in the ANSWER section and the the other records
39
  // and we want to shuffle the other records only
40

41
  // First we scan for the first non-CNAME ANSWER record
42
  for (first = rrs.begin(); first != rrs.end(); ++first) {
×
43
    if (first->dr.d_place == DNSResourceRecord::ANSWER && first->dr.d_type != QType::CNAME) {
×
44
      break;
×
45
    }
×
46
  }
×
47
  // And then for one past the last ANSWER record
48
  for (second = first; second != rrs.end(); ++second) {
×
49
    if (second->dr.d_place != DNSResourceRecord::ANSWER) {
×
50
      break;
×
51
    }
×
52
  }
×
53

54
  // Now shuffle the non-CNAME ANSWER records
55
  dns_random_engine randomEngine;
×
56
  if (second - first > 1) {
×
57
    shuffle(first, second, randomEngine);
×
58
  }
×
59

60
  // now shuffle the ADDITIONAL records in the same manner as the ANSWER records
61
  for (first = second; first != rrs.end(); ++first) {
×
62
    if (first->dr.d_place == DNSResourceRecord::ADDITIONAL && first->dr.d_type != QType::CNAME) {
×
63
      break;
×
64
    }
×
65
  }
×
66
  for (second = first; second != rrs.end(); ++second) {
×
67
    if (second->dr.d_place != DNSResourceRecord::ADDITIONAL) {
×
68
      break;
×
69
    }
×
70
  }
×
71

72
  if (second - first > 1) {
×
73
    shuffle(first, second, randomEngine);
×
74
  }
×
75
  // we don't shuffle the rest
76
}
×
77

78
// shuffle, maintaining some semblance of order
79
static void shuffle(std::vector<DNSRecord>& rrs, bool includingAdditionals)
80
{
2,263✔
81
  // This shuffles in the same style as the above method, keeping CNAME in the front and RRSIGs at the end
82
  std::vector<DNSRecord>::iterator first;
2,263✔
83
  std::vector<DNSRecord>::iterator second;
2,263✔
84

85
  for (first = rrs.begin(); first != rrs.end(); ++first) {
4,311✔
86
    if (first->d_place == DNSResourceRecord::ANSWER && first->d_type != QType::CNAME) {
3,936✔
87
      break;
1,888✔
88
    }
1,888✔
89
  }
3,936✔
90
  for (second = first; second != rrs.end(); ++second) {
6,213✔
91
    if (second->d_place != DNSResourceRecord::ANSWER || second->d_type == QType::RRSIG) {
4,406✔
92
      break;
456✔
93
    }
456✔
94
  }
4,406✔
95

96
  pdns::dns_random_engine randomEngine;
2,263✔
97
  if (second - first > 1) {
2,263✔
98
    shuffle(first, second, randomEngine);
560✔
99
  }
560✔
100

101
  if (!includingAdditionals) {
2,263!
102
    return;
2,263✔
103
  }
2,263✔
104

105
  // now shuffle the additional records
106
  for (first = second; first != rrs.end(); ++first) {
×
107
    if (first->d_place == DNSResourceRecord::ADDITIONAL && first->d_type != QType::CNAME) {
×
108
      break;
×
109
    }
×
110
  }
×
111
  for (second = first; second != rrs.end(); ++second) {
×
112
    if (second->d_place != DNSResourceRecord::ADDITIONAL) {
×
113
      break;
×
114
    }
×
115
  }
×
116

117
  if (second - first > 1) {
×
118
    shuffle(first, second, randomEngine);
×
119
  }
×
120
  // we don't shuffle the rest
121
}
×
122

123
static uint16_t mapTypesToOrder(uint16_t type)
124
{
19,680✔
125
  if (type == QType::CNAME) {
19,680✔
126
    return 0;
5,143✔
127
  }
5,143✔
128
  if (type == QType::RRSIG) {
14,537✔
129
    return 65535;
1,997✔
130
  }
1,997✔
131
  return 1;
12,540✔
132
}
14,537✔
133

134
// make sure rrs is sorted in d_place order to avoid surprises later
135
// then shuffle the parts that desire shuffling
136
void pdns::orderAndShuffle(vector<DNSRecord>& rrs, bool includingAdditionals)
137
{
2,263✔
138
  std::stable_sort(rrs.begin(), rrs.end(), [](const DNSRecord& lhs, const DNSRecord& rhs) {
9,844✔
139
    return std::tuple(lhs.d_place, mapTypesToOrder(lhs.d_type)) < std::tuple(rhs.d_place, mapTypesToOrder(rhs.d_type));
9,840✔
140
  });
9,840✔
141
  shuffle(rrs, includingAdditionals);
2,263✔
142
}
2,263✔
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