Coverage Report

Created: 2025-09-05 06:36

/src/pdns/pdns/dns_random.hh
Line
Count
Source (jump to first uncovered line)
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 <cstdint>
24
#include <limits>
25
#include <string>
26
27
#include <ext/arc4random/arc4random.hh>
28
29
inline uint32_t dns_random(uint32_t upper_bound)
30
0
{
31
0
  return arc4random_uniform(upper_bound);
32
0
}
33
34
inline uint32_t dns_random_uint32()
35
0
{
36
0
  return arc4random();
37
0
}
38
39
inline uint16_t dns_random_uint16()
40
0
{
41
0
  return arc4random() & 0xffff;
42
0
}
43
44
inline void dns_random(void* buf, size_t size)
45
0
{
46
0
  arc4random_buf(buf, size);
47
0
}
48
49
namespace pdns
50
{
51
struct dns_random_engine
52
{
53
54
  using result_type = uint32_t;
55
56
  static constexpr result_type min()
57
0
  {
58
0
    return 0;
59
0
  }
60
61
  static constexpr result_type max()
62
0
  {
63
0
    return std::numeric_limits<result_type>::max();
64
0
  }
65
66
  result_type operator()()
67
0
  {
68
0
    return dns_random_uint32();
69
0
  }
70
};
71
72
/* minimum value that a PRNG should return for this upper bound to avoid a modulo bias */
73
inline unsigned int random_minimum_acceptable_value(uint32_t upper_bound)
74
0
{
75
0
  /* Parts of this code come from arc4random_uniform */
76
0
  /* To avoid "modulo bias" for some methods, calculate
77
0
     minimum acceptable value for random number to improve
78
0
     uniformity.
79
0
80
0
     On applicable rngs, we loop until the rng spews out
81
0
     value larger than min, and then take modulo out of that.
82
0
  */
83
0
  unsigned int min = 0;
84
0
#if (ULONG_MAX > 0xffffffffUL)
85
0
  min = 0x100000000UL % upper_bound;
86
0
#else
87
0
  /* Calculate (2**32 % upper_bound) avoiding 64-bit math */
88
0
  if (upper_bound > 0x80000000)
89
0
    min = 1 + ~upper_bound; /* 2**32 - upper_bound */
90
0
  else {
91
0
    /* (2**32 - (x * 2)) % x == 2**32 % x when x <= 2**31 */
92
0
    min = ((0xffffffff - (upper_bound * 2)) + 1) % upper_bound;
93
0
  }
94
0
#endif
95
0
  return min;
96
0
}
97
}