]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/adaptation/ServiceConfig.cc
2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
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.
9 /* DEBUG: section 93 Adaptation */
12 #include "adaptation/ServiceConfig.h"
14 #include "ConfigParser.h"
15 #include "debug/Stream.h"
20 Adaptation::ServiceConfig::ServiceConfig():
21 port(-1), method(methodNone
), point(pointNone
),
22 bypass(false), maxConn(-1), onOverload(srvWait
),
23 routing(false), ipv6(false)
27 Adaptation::ServiceConfig::methodStr() const
29 return Adaptation::methodStr(method
);
33 Adaptation::ServiceConfig::vectPointStr() const
35 return Adaptation::vectPointStr(point
);
39 Adaptation::ServiceConfig::parseMethod(const char *str
) const
41 if (!strncasecmp(str
, "REQMOD", 6))
42 return Adaptation::methodReqmod
;
44 if (!strncasecmp(str
, "RESPMOD", 7))
45 return Adaptation::methodRespmod
;
47 return Adaptation::methodNone
;
51 Adaptation::ServiceConfig::parseVectPoint(const char *service_configConfig
) const
53 const char *t
= service_configConfig
;
54 const char *q
= strchr(t
, '_');
59 if (!strcmp(t
, "precache"))
60 return Adaptation::pointPreCache
;
62 if (!strcmp(t
, "postcache"))
63 return Adaptation::pointPostCache
;
65 return Adaptation::pointNone
;
69 Adaptation::ServiceConfig::parse()
71 key
= ConfigParser::NextToken();
72 String method_point
= ConfigParser::NextToken();
73 if (!method_point
.size()) {
74 debugs(3, DBG_CRITICAL
, "ERROR: " << cfg_filename
<< ':' << config_lineno
<< ": " <<
75 "Missing vectoring point in adaptation service definition");
79 method
= parseMethod(method_point
.termedBuf());
80 point
= parseVectPoint(method_point
.termedBuf());
81 if (method
== Adaptation::methodNone
&& point
== Adaptation::pointNone
) {
82 debugs(3, DBG_CRITICAL
, "ERROR: " << cfg_filename
<< ':' << config_lineno
<< ": " <<
83 "Unknown vectoring point '" << method_point
<< "' in adaptation service definition");
87 // reset optional parameters in case we are reconfiguring
88 bypass
= routing
= false;
90 // handle optional service name=value parameters
91 bool grokkedUri
= false;
92 bool onOverloadSet
= false;
93 std::set
<std::string
> options
;
95 while (char *option
= ConfigParser::NextToken()) {
96 const char *name
= option
;
97 const char *value
= "";
98 if (strcmp(option
, "0") == 0) { // backward compatibility
101 debugs(3, DBG_PARSE_NOTE(DBG_IMPORTANT
), "WARNING: UPGRADE: Please use 'bypass=off' option to disable service bypass");
102 } else if (strcmp(option
, "1") == 0) { // backward compatibility
105 debugs(3, DBG_PARSE_NOTE(DBG_IMPORTANT
), "WARNING: UPGRADE: Please use 'bypass=on' option to enable service bypass");
107 char *eq
= strstr(option
, "=");
108 const char *sffx
= strstr(option
, "://");
109 if (!eq
|| (sffx
&& sffx
< eq
)) { //no "=" or has the form "icap://host?arg=val"
112 } else { // a normal name=value option
113 *eq
= '\0'; // terminate option name
114 value
= eq
+ 1; // skip '='
118 // Check if option is set twice
119 if (options
.find(name
) != options
.end()) {
120 debugs(3, DBG_CRITICAL
, "ERROR: " << cfg_filename
<< ':' << config_lineno
<< ": " <<
121 "Duplicate option \"" << name
<< "\" in adaptation service definition");
124 options
.insert(name
);
126 bool grokked
= false;
127 if (strcmp(name
, "bypass") == 0) {
128 grokked
= grokBool(bypass
, name
, value
);
129 } else if (strcmp(name
, "routing") == 0)
130 grokked
= grokBool(routing
, name
, value
);
131 else if (strcmp(name
, "uri") == 0)
132 grokked
= grokkedUri
= grokUri(value
);
133 else if (strcmp(name
, "ipv6") == 0) {
134 grokked
= grokBool(ipv6
, name
, value
);
135 if (grokked
&& ipv6
&& !Ip::EnableIpv6
)
136 debugs(3, DBG_PARSE_NOTE(DBG_IMPORTANT
), "WARNING: IPv6 is disabled. ICAP service option ignored.");
137 } else if (strcmp(name
, "max-conn") == 0)
138 grokked
= grokLong(maxConn
, name
, value
);
139 else if (strcmp(name
, "on-overload") == 0) {
140 grokked
= grokOnOverload(onOverload
, value
);
141 onOverloadSet
= true;
142 } else if (strcmp(name
, "connection-encryption") == 0) {
143 bool encrypt
= false;
144 grokked
= grokBool(encrypt
, name
, value
);
145 connectionEncryption
.configure(encrypt
);
146 } else if (strncmp(name
, "ssl", 3) == 0 || strncmp(name
, "tls-", 4) == 0) {
148 debugs(3, DBG_PARSE_NOTE(DBG_IMPORTANT
), "WARNING: adaptation option '" << name
<< "' requires --with-openssl. ICAP service option ignored.");
150 // name prefix is "ssl" or "tls-"
151 std::string tmp
= name
+ (name
[0] == 's' ? 3 : 4);
154 secure
.parse(tmp
.c_str());
158 grokked
= grokExtension(name
, value
);
164 // set default on-overload value if needed
166 onOverload
= bypass
? srvBypass
: srvWait
;
168 // disable the TLS NPN extension if encrypted.
169 // Squid advertises "http/1.1", which is wrong for ICAPS.
170 if (secure
.encryptTransport
)
171 secure
.parse("no-npn");
173 // is the service URI set?
175 debugs(3, DBG_CRITICAL
, "ERROR: " << cfg_filename
<< ':' << config_lineno
<< ": " <<
176 "No \"uri\" option in adaptation service definition");
180 debugs(3,5, cfg_filename
<< ':' << config_lineno
<< ": " <<
181 "adaptation_service " << key
<< ' ' <<
182 methodStr() << "_" << vectPointStr() << ' ' <<
183 bypass
<< routing
<< ' ' <<
190 Adaptation::ServiceConfig::grokUri(const char *value
)
192 // TODO: find core code that parses URLs and extracts various parts
193 // AYJ: most of this is duplicate of AnyP::Uri::parse()
195 if (!value
|| !*value
) {
196 debugs(3, DBG_CRITICAL
, cfg_filename
<< ':' << config_lineno
<< ": " <<
197 "empty adaptation service URI");
203 // extract scheme and use it as the service_configConfig protocol
204 const char *schemeSuffix
= "://";
205 const String::size_type schemeEnd
= uri
.find(schemeSuffix
);
206 if (schemeEnd
!= String::npos
)
207 protocol
=uri
.substr(0,schemeEnd
);
209 debugs(3, 5, cfg_filename
<< ':' << config_lineno
<< ": " <<
210 "service protocol is " << protocol
);
212 if (protocol
.size() == 0)
216 const char *s
= uri
.termedBuf() + protocol
.size() + strlen(schemeSuffix
);
220 bool have_port
= false;
225 if ((t
= strchr(s
, ']')) == nullptr)
230 if ((e
= strchr(t
, ':')) != nullptr) {
232 } else if ((e
= strchr(t
, '/')) != nullptr) {
238 if ((e
= strchr(s
, ':')) != nullptr) {
240 } else if ((e
= strchr(s
, '/')) != nullptr) {
250 if (secure
.sslDomain
.isEmpty())
251 secure
.sslDomain
.assign(host
.rawBuf(), host
.size());
259 if ((e
= strchr(s
, '/')) != nullptr) {
261 const unsigned long p
= strtoul(s
, &t
, 0);
263 if (p
> 65535) // port value is too high
266 port
= static_cast<int>(p
);
268 if (t
!= e
) // extras after the port
278 // if no port, the caller may use service_configConfigs or supply the default if needed
285 debugs(3, DBG_CRITICAL
, cfg_filename
<< ':' << config_lineno
<< ": " <<
286 "long resource name (>1024), probably wrong");
289 resource
.assign(s
, len
+ 1);
294 Adaptation::ServiceConfig::grokBool(bool &var
, const char *name
, const char *value
)
296 if (!strcmp(value
, "0") || !strcmp(value
, "off"))
298 else if (!strcmp(value
, "1") || !strcmp(value
, "on"))
301 debugs(3, DBG_CRITICAL
, cfg_filename
<< ':' << config_lineno
<< ": " <<
302 "wrong value for boolean " << name
<< "; " <<
303 "'0', '1', 'on', or 'off' expected but got: " << value
);
311 Adaptation::ServiceConfig::grokLong(long &var
, const char *name
, const char *value
)
314 const long p
= strtol(value
, &bad
, 0);
315 if (p
< 0 || bad
== value
) {
316 debugs(3, DBG_CRITICAL
, "ERROR: " << cfg_filename
<< ':' <<
317 config_lineno
<< ": " << "wrong value for " << name
<< "; " <<
318 "a non-negative integer expected but got: " << value
);
326 Adaptation::ServiceConfig::grokOnOverload(SrvBehaviour
&var
, const char *value
)
328 if (strcmp(value
, "block") == 0)
330 else if (strcmp(value
, "bypass") == 0)
332 else if (strcmp(value
, "wait") == 0)
334 else if (strcmp(value
, "force") == 0)
337 debugs(3, DBG_CRITICAL
, "ERROR: " << cfg_filename
<< ':' <<
338 config_lineno
<< ": " << "wrong value for on-overload; " <<
339 "'block', 'bypass', 'wait' or 'force' expected but got: " << value
);
346 Adaptation::ServiceConfig::grokExtension(const char *name
, const char *value
)
348 // we do not accept extensions by default
349 debugs(3, DBG_CRITICAL
, "ERROR: " << cfg_filename
<< ':' << config_lineno
<< ": " <<
350 "ERROR: unknown adaptation service option: " <<
351 name
<< '=' << value
);