]> git.ipfire.org Git - thirdparty/squid.git/blame - src/adaptation/Config.cc
Source Format Enforcement (#1234)
[thirdparty/squid.git] / src / adaptation / Config.cc
CommitLineData
64bdef96 1/*
b8ae064d 2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
64bdef96 3 *
bbc27441
AJ
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.
64bdef96
AR
7 */
8
582c2af2 9#include "squid.h"
71be37e0 10#include "acl/FilledChecklist.h"
582c2af2
FC
11#include "acl/Gadgets.h"
12#include "adaptation/AccessRule.h"
64bdef96 13#include "adaptation/Config.h"
582c2af2 14#include "adaptation/History.h"
64bdef96 15#include "adaptation/Service.h"
62c7f90e 16#include "adaptation/ServiceGroups.h"
aa3b39af 17#include "cache_cf.h"
582c2af2 18#include "ConfigParser.h"
675b8408 19#include "debug/Messages.h"
582c2af2
FC
20#include "globals.h"
21#include "HttpReply.h"
71be37e0 22#include "HttpRequest.h"
582c2af2 23#include "Store.h"
64bdef96 24
c8ea3cc0
FC
25#include <algorithm>
26
8f361c50 27bool Adaptation::Config::Enabled = false;
aee3523a 28char *Adaptation::Config::masterx_shared_name = nullptr;
a22e6cd3 29int Adaptation::Config::service_iteration_limit = 16;
22fff3bf
AR
30int Adaptation::Config::send_client_ip = false;
31int Adaptation::Config::send_username = false;
32int Adaptation::Config::use_indirect_client = true;
4668df3d
CT
33static const char *protectedFieldNamesRaw[] = {
34 "Allow",
35 "Date",
d7f4a0b7 36 "Encapsulated",
4668df3d 37 "ISTag",
d7f4a0b7 38 "Max-Connections",
4668df3d
CT
39 "Methods",
40 "Opt-body-type",
d7f4a0b7 41 "Options-TTL",
d7f4a0b7 42 "Preview",
4668df3d
CT
43 "Service",
44 "Service-ID",
d7f4a0b7 45 "Transfer-Complete",
4668df3d
CT
46 "Transfer-Ignore",
47 "Transfer-Preview"
d7f4a0b7 48};
4668df3d
CT
49static const Notes::Keys protectedFieldNames(std::begin(protectedFieldNamesRaw), std::end(protectedFieldNamesRaw));
50Notes Adaptation::Config::metaHeaders("ICAP header", &protectedFieldNames);
c302ddb5 51bool Adaptation::Config::needHistory = false;
8f361c50 52
e1e90d26
AR
53Adaptation::ServiceConfig*
54Adaptation::Config::newServiceConfig() const
55{
56 return new ServiceConfig();
57}
58
7e8c4ee9
CT
59void
60Adaptation::Config::removeService(const String& service)
61{
62 removeRule(service);
63 const Groups& groups = AllGroups();
64 for (unsigned int i = 0; i < groups.size(); ) {
65 const ServiceGroupPointer group = groups[i];
66 const ServiceGroup::Store& services = group->services;
67 typedef ServiceGroup::Store::const_iterator SGSI;
68 for (SGSI it = services.begin(); it != services.end(); ++it) {
69 if (*it == service) {
70 group->removedServices.push_back(service);
6e1410f9
FC
71 ServiceGroup::Store::iterator newend;
72 newend = std::remove(group->services.begin(), group->services.end(), service);
73 group->services.resize(newend-group->services.begin());
c8ea3cc0 74 debugs(93, 5, "adaptation service " << service <<
7e8c4ee9
CT
75 " removed from group " << group->id);
76 break;
77 }
78 }
79 if (services.empty()) {
80 removeRule(group->id);
6e1410f9
FC
81 Groups::iterator newend;
82 newend = std::remove(AllGroups().begin(), AllGroups().end(), group);
83 AllGroups().resize(newend-AllGroups().begin());
7e8c4ee9
CT
84 } else {
85 ++i;
86 }
87 }
88}
89
c302ddb5
CT
90Adaptation::ServiceConfigPointer
91Adaptation::Config::findServiceConfig(const String &service)
92{
93 typedef ServiceConfigs::const_iterator SCI;
94 const ServiceConfigs& configs = serviceConfigs;
95 for (SCI cfg = configs.begin(); cfg != configs.end(); ++cfg) {
96 if ((*cfg)->key == service)
97 return *cfg;
98 }
aee3523a 99 return nullptr;
c302ddb5
CT
100}
101
7e8c4ee9
CT
102void
103Adaptation::Config::removeRule(const String& id)
104{
105 typedef AccessRules::const_iterator ARI;
106 const AccessRules& rules = AllRules();
107 for (ARI it = rules.begin(); it != rules.end(); ++it) {
108 AccessRule* rule = *it;
109 if (rule->groupId == id) {
c8ea3cc0 110 debugs(93, 5, "removing access rules for:" << id);
6e1410f9
FC
111 AccessRules::iterator newend;
112 newend = std::remove(AllRules().begin(), AllRules().end(), rule);
113 AllRules().resize(newend-AllRules().begin());
7e8c4ee9
CT
114 delete (rule);
115 break;
116 }
117 }
118}
119
120void
121Adaptation::Config::clear()
122{
bf95c10a 123 debugs(93, 3, "rules: " << AllRules().size() << ", groups: " <<
7e8c4ee9
CT
124 AllGroups().size() << ", services: " << serviceConfigs.size());
125 typedef ServiceConfigs::const_iterator SCI;
126 const ServiceConfigs& configs = serviceConfigs;
127 for (SCI cfg = configs.begin(); cfg != configs.end(); ++cfg)
128 removeService((*cfg)->key);
c33a88ca 129 serviceConfigs.clear();
bf95c10a 130 debugs(93, 3, "rules: " << AllRules().size() << ", groups: " <<
7e8c4ee9
CT
131 AllGroups().size() << ", services: " << serviceConfigs.size());
132}
133
64bdef96
AR
134void
135Adaptation::Config::parseService()
136{
e1e90d26 137 ServiceConfigPointer cfg = newServiceConfig();
a22e6cd3
AR
138 if (!cfg->parse()) {
139 fatalf("%s:%d: malformed adaptation service configuration",
e1381638 140 cfg_filename, config_lineno);
a22e6cd3 141 }
64bdef96
AR
142 serviceConfigs.push_back(cfg);
143}
144
145void
146Adaptation::Config::freeService()
147{
76fc7e57
AJ
148 FreeAccess();
149 FreeServiceGroups();
150
151 DetachServices();
152
c33a88ca 153 serviceConfigs.clear();
64bdef96
AR
154}
155
156void
157Adaptation::Config::dumpService(StoreEntry *entry, const char *name) const
158{
159 typedef Services::iterator SCI;
160 for (SCI i = AllServices().begin(); i != AllServices().end(); ++i) {
161 const ServiceConfig &cfg = (*i)->cfg();
88df846b
CT
162 bool isEcap = cfg.protocol.caseCmp("ecap") == 0;
163 bool isIcap = !isEcap;
164 const char *optConnectionEncryption = "";
165 // Print connections_encrypted option if no default value is used
166 if (cfg.secure.encryptTransport && !cfg.connectionEncryption)
167 optConnectionEncryption = " connection-encryption=off";
168 else if (isEcap && !cfg.connectionEncryption)
169 optConnectionEncryption = " connection-encryption=off";
170 else if (isIcap && !cfg.secure.encryptTransport && cfg.connectionEncryption)
171 optConnectionEncryption = " connection-encryption=on";
172
173 storeAppendPrintf(entry, "%s " SQUIDSTRINGPH " %s_%s %d " SQUIDSTRINGPH "%s\n",
af6a12ee
AJ
174 name,
175 SQUIDSTRINGPRINT(cfg.key),
176 cfg.methodStr(), cfg.vectPointStr(), cfg.bypass,
88df846b 177 SQUIDSTRINGPRINT(cfg.uri),
ff89bfa0 178
88df846b 179 optConnectionEncryption);
64bdef96
AR
180 }
181}
182
7e8c4ee9 183bool
64bdef96
AR
184Adaptation::Config::finalize()
185{
7e8c4ee9
CT
186 if (!onoff) {
187 clear();
188 return false;
189 }
190
64bdef96 191 // create service reps from service configs
e1e90d26
AR
192 int created = 0;
193
194 typedef ServiceConfigs::const_iterator VISCI;
195 const ServiceConfigs &configs = serviceConfigs;
62c7f90e 196 for (VISCI i = configs.begin(); i != configs.end(); ++i) {
e1e90d26 197 const ServiceConfigPointer cfg = *i;
aee3523a 198 if (FindService(cfg->key) != nullptr) {
fa84c01d 199 debugs(93, DBG_CRITICAL, "ERROR: Duplicate adaptation service name: " <<
e1e90d26 200 cfg->key);
26ac0430
AJ
201 continue; // TODO: make fatal
202 }
e1e90d26 203 ServicePointer s = createService(cfg);
aee3523a 204 if (s != nullptr) {
62c7f90e 205 AllServices().push_back(s);
742a021b 206 ++created;
e1e90d26 207 }
64bdef96
AR
208 }
209
bf95c10a 210 debugs(93,3, "Created " << created << " adaptation services");
e1e90d26
AR
211
212 // services remember their configs; we do not have to
c33a88ca 213 serviceConfigs.clear();
7e8c4ee9 214 return true;
64bdef96
AR
215}
216
62c7f90e
AR
217// poor man for_each
218template <class Collection>
219static void
220FinalizeEach(Collection &collection, const char *label)
64bdef96 221{
62c7f90e
AR
222 typedef typename Collection::iterator CI;
223 for (CI i = collection.begin(); i != collection.end(); ++i)
224 (*i)->finalize();
64bdef96 225
bf95c10a 226 debugs(93,2, "Initialized " << collection.size() << ' ' << label);
64bdef96
AR
227}
228
229void
8f361c50 230Adaptation::Config::Finalize(bool enabled)
64bdef96 231{
8f361c50 232 Enabled = enabled;
c59baaa8 233 debugs(93, Important(11), "Adaptation support is " << (Enabled ? "on" : "off."));
8f361c50 234
62c7f90e
AR
235 FinalizeEach(AllServices(), "message adaptation services");
236 FinalizeEach(AllGroups(), "message adaptation service groups");
237 FinalizeEach(AllRules(), "message adaptation access rules");
238}
64bdef96
AR
239
240void
62c7f90e 241Adaptation::Config::ParseServiceSet()
64bdef96 242{
a22e6cd3
AR
243 Adaptation::Config::ParseServiceGroup(new ServiceSet);
244}
245
246void
247Adaptation::Config::ParseServiceChain()
248{
249 Adaptation::Config::ParseServiceGroup(new ServiceChain);
250}
251
252void
253Adaptation::Config::ParseServiceGroup(ServiceGroupPointer g)
254{
aee3523a 255 assert(g != nullptr);
62c7f90e
AR
256 g->parse();
257 AllGroups().push_back(g);
64bdef96
AR
258}
259
260void
a22e6cd3 261Adaptation::Config::FreeServiceGroups()
64bdef96 262{
62c7f90e 263 while (!AllGroups().empty()) {
a22e6cd3 264 // groups are refcounted so we do not explicitly delete them
b6b637eb
AR
265 AllGroups().pop_back();
266 }
64bdef96
AR
267}
268
269void
a22e6cd3 270Adaptation::Config::DumpServiceGroups(StoreEntry *entry, const char *name)
64bdef96 271{
62c7f90e
AR
272 typedef Groups::iterator GI;
273 for (GI i = AllGroups().begin(); i != AllGroups().end(); ++i)
2c1fd837 274 storeAppendPrintf(entry, "%s " SQUIDSTRINGPH "\n", name, SQUIDSTRINGPRINT((*i)->id));
62c7f90e 275}
64bdef96 276
62c7f90e
AR
277void
278Adaptation::Config::ParseAccess(ConfigParser &parser)
279{
2eceb328 280 String groupId = ConfigParser::NextToken();
287bbe9a 281 AccessRule *r;
899fad67 282 if (!(r=FindRuleByGroupId(groupId))) {
af6a12ee
AJ
283 r = new AccessRule(groupId);
284 AllRules().push_back(r);
899fad67 285 }
62c7f90e 286 r->parse(parser);
62c7f90e 287}
64bdef96
AR
288
289void
62c7f90e 290Adaptation::Config::FreeAccess()
64bdef96 291{
62c7f90e
AR
292 while (!AllRules().empty()) {
293 delete AllRules().back();
294 AllRules().pop_back();
b6b637eb 295 }
64bdef96
AR
296}
297
298void
62c7f90e 299Adaptation::Config::DumpAccess(StoreEntry *entry, const char *name)
64bdef96
AR
300{
301 LOCAL_ARRAY(char, nom, 64);
302
62c7f90e
AR
303 typedef AccessRules::iterator CI;
304 for (CI i = AllRules().begin(); i != AllRules().end(); ++i) {
2c1fd837 305 snprintf(nom, 64, "%s " SQUIDSTRINGPH, name, SQUIDSTRINGPRINT((*i)->groupId));
62c7f90e 306 dump_acl_access(entry, nom, (*i)->acl);
b6b637eb 307 }
64bdef96
AR
308}
309
c9568681 310Adaptation::Config::Config() :
f53969cc
SM
311 onoff(0), service_failure_limit(0), oldest_service_failure(0),
312 service_revival_delay(0)
c9568681 313{}
64bdef96 314
26ac0430 315// XXX: this is called for ICAP and eCAP configs, but deals mostly
62c7f90e 316// with global arrays shared by those individual configs
64bdef96
AR
317Adaptation::Config::~Config()
318{
62c7f90e 319 freeService();
64bdef96 320}
f53969cc 321