]> git.ipfire.org Git - thirdparty/squid.git/blob - src/acl/Random.cc
84f5376902376d6a905348f675320a4efa94cb2c
[thirdparty/squid.git] / src / acl / Random.cc
1 /*
2 * Copyright (C) 1996-2022 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9 /* DEBUG: section 28 Access Control */
10
11 #include "squid.h"
12 #include "acl/FilledChecklist.h"
13 #include "acl/Random.h"
14 #include "debug/Stream.h"
15 #include "Parsing.h"
16 #include "wordlist.h"
17
18 #include <random>
19
20 ACLRandom::ACLRandom(char const *theClass) : data(0.0), class_(theClass)
21 {
22 memset(pattern, 0, sizeof(pattern));
23 }
24
25 ACLRandom::~ACLRandom()
26 { }
27
28 char const *
29 ACLRandom::typeString() const
30 {
31 return class_;
32 }
33
34 bool
35 ACLRandom::empty () const
36 {
37 return data == 0.0;
38 }
39
40 bool
41 ACLRandom::valid() const
42 {
43 return !empty();
44 }
45
46 /*******************/
47 /* aclParseRandomList */
48 /*******************/
49 void
50 ACLRandom::parse()
51 {
52 char bufa[256], bufb[256];
53
54 char *t = ConfigParser::strtokFile();
55 if (!t) {
56 debugs(28, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: ACL random missing pattern");
57 return;
58 }
59
60 debugs(28, 5, "aclParseRandomData: " << t);
61
62 // seed random generator ...
63 srand(time(nullptr));
64
65 if (sscanf(t, "%[0-9]:%[0-9]", bufa, bufb) == 2) {
66 int a = xatoi(bufa);
67 int b = xatoi(bufb);
68 if (a <= 0 || b <= 0) {
69 debugs(28, DBG_CRITICAL, "ERROR: ACL random with bad pattern: '" << t << "'");
70 return;
71 } else
72 data = a / (double)(a+b);
73 } else if (sscanf(t, "%[0-9]/%[0-9]", bufa, bufb) == 2) {
74 int a = xatoi(bufa);
75 int b = xatoi(bufb);
76 if (a <= 0 || b <= 0 || a > b) {
77 debugs(28, DBG_CRITICAL, "ERROR: ACL random with bad pattern: '" << t << "'");
78 return;
79 } else
80 data = (double) a / (double) b;
81 } else if (sscanf(t, "0.%[0-9]", bufa) == 1) {
82 data = atof(t);
83 } else {
84 debugs(28, DBG_CRITICAL, "ERROR: ACL random with bad pattern: '" << t << "'");
85 return;
86 }
87
88 // save the exact input pattern. so we can display it later.
89 memcpy(pattern, t, min(sizeof(pattern)-1,strlen(t)));
90 }
91
92 int
93 ACLRandom::match(ACLChecklist *)
94 {
95 // make up the random value.
96 // The fixed-value default seed is fine because we are
97 // actually matching whether the random value is above
98 // or below the configured threshold ratio.
99 static std::mt19937 mt;
100 static std::uniform_real_distribution<> dist(0, 1);
101
102 const double random = dist(mt);
103
104 debugs(28, 3, "ACL Random: " << name << " " << pattern << " test: " << data << " > " << random << " = " << ((data > random)?"MATCH":"NO MATCH") );
105 return (data > random)?1:0;
106 }
107
108 SBufList
109 ACLRandom::dump() const
110 {
111 SBufList sl;
112 sl.push_back(SBuf(pattern));
113 return sl;
114 }
115