ServiceConfig.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2017 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 93 Adaptation */
10 
11 #include "squid.h"
13 #include "ConfigParser.h"
14 #include "Debug.h"
15 #include "globals.h"
16 #include "ip/tools.h"
17 #include <set>
18 
20  port(-1), method(methodNone), point(pointNone),
21  bypass(false), maxConn(-1), onOverload(srvWait),
22  routing(false), ipv6(false)
23 {}
24 
25 const char *
27 {
29 }
30 
31 const char *
33 {
34  return Adaptation::vectPointStr(point);
35 }
36 
39 {
40  if (!strncasecmp(str, "REQMOD", 6))
42 
43  if (!strncasecmp(str, "RESPMOD", 7))
45 
47 }
48 
50 Adaptation::ServiceConfig::parseVectPoint(const char *service_configConfig) const
51 {
52  const char *t = service_configConfig;
53  const char *q = strchr(t, '_');
54 
55  if (q)
56  t = q + 1;
57 
58  if (!strcmp(t, "precache"))
60 
61  if (!strcmp(t, "postcache"))
63 
64  return Adaptation::pointNone;
65 }
66 
67 bool
69 {
71  String method_point = ConfigParser::NextToken();
72  if (!method_point.size()) {
73  debugs(3, DBG_CRITICAL, "ERROR: " << cfg_filename << ':' << config_lineno << ": " <<
74  "Missing vectoring point in adaptation service definition");
75  return false;
76  }
77 
78  method = parseMethod(method_point.termedBuf());
79  point = parseVectPoint(method_point.termedBuf());
81  debugs(3, DBG_CRITICAL, "ERROR: " << cfg_filename << ':' << config_lineno << ": " <<
82  "Unknown vectoring point '" << method_point << "' in adaptation service definition");
83  return false;
84  }
85 
86  // reset optional parameters in case we are reconfiguring
87  bypass = routing = false;
88 
89  // handle optional service name=value parameters
90  bool grokkedUri = false;
91  bool onOverloadSet = false;
92  std::set<std::string> options;
93 
94  while (char *option = ConfigParser::NextToken()) {
95  const char *name = option;
96  const char *value = "";
97  if (strcmp(option, "0") == 0) { // backward compatibility
98  name = "bypass";
99  value = "off";
100  debugs(3, DBG_PARSE_NOTE(DBG_IMPORTANT), "UPGRADE: Please use 'bypass=off' option to disable service bypass");
101  } else if (strcmp(option, "1") == 0) { // backward compatibility
102  name = "bypass";
103  value = "on";
104  debugs(3, DBG_PARSE_NOTE(DBG_IMPORTANT), "UPGRADE: Please use 'bypass=on' option to enable service bypass");
105  } else {
106  char *eq = strstr(option, "=");
107  const char *sffx = strstr(option, "://");
108  if (!eq || (sffx && sffx < eq)) { //no "=" or has the form "icap://host?arg=val"
109  name = "uri";
110  value = option;
111  } else { // a normal name=value option
112  *eq = '\0'; // terminate option name
113  value = eq + 1; // skip '='
114  }
115  }
116 
117  // Check if option is set twice
118  if (options.find(name) != options.end()) {
119  debugs(3, DBG_CRITICAL, "ERROR: " << cfg_filename << ':' << config_lineno << ": " <<
120  "Duplicate option \"" << name << "\" in adaptation service definition");
121  return false;
122  }
123  options.insert(name);
124 
125  bool grokked = false;
126  if (strcmp(name, "bypass") == 0) {
127  grokked = grokBool(bypass, name, value);
128  } else if (strcmp(name, "routing") == 0)
129  grokked = grokBool(routing, name, value);
130  else if (strcmp(name, "uri") == 0)
131  grokked = grokkedUri = grokUri(value);
132  else if (strcmp(name, "ipv6") == 0) {
133  grokked = grokBool(ipv6, name, value);
134  if (grokked && ipv6 && !Ip::EnableIpv6)
135  debugs(3, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: IPv6 is disabled. ICAP service option ignored.");
136  } else if (strcmp(name, "max-conn") == 0)
137  grokked = grokLong(maxConn, name, value);
138  else if (strcmp(name, "on-overload") == 0) {
139  grokked = grokOnOverload(onOverload, value);
140  onOverloadSet = true;
141  } else if (strcmp(name, "connection-encryption") == 0) {
142  bool encrypt = false;
143  grokked = grokBool(encrypt, name, value);
144  connectionEncryption.configure(encrypt);
145  } else if (strncmp(name, "ssl", 3) == 0 || strncmp(name, "tls-", 4) == 0) {
146 #if !USE_OPENSSL
147  debugs(3, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: adaptation option '" << name << "' requires --with-openssl. ICAP service option ignored.");
148 #else
149  // name prefix is "ssl" or "tls-"
150  std::string tmp = name + (name[0] == 's' ? 3 : 4);
151  tmp += "=";
152  tmp += value;
153  secure.parse(tmp.c_str());
154  grokked = true;
155 #endif
156  } else
157  grokked = grokExtension(name, value);
158 
159  if (!grokked)
160  return false;
161  }
162 
163  // set default on-overload value if needed
164  if (!onOverloadSet)
165  onOverload = bypass ? srvBypass : srvWait;
166 
167  // disable the TLS NPN extension if encrypted.
168  // Squid advertises "http/1.1", which is wrong for ICAPS.
169  if (secure.encryptTransport)
170  secure.parse("no-npn");
171 
172  // is the service URI set?
173  if (!grokkedUri) {
174  debugs(3, DBG_CRITICAL, "ERROR: " << cfg_filename << ':' << config_lineno << ": " <<
175  "No \"uri\" option in adaptation service definition");
176  return false;
177  }
178 
179  debugs(3,5, cfg_filename << ':' << config_lineno << ": " <<
180  "adaptation_service " << key << ' ' <<
181  methodStr() << "_" << vectPointStr() << ' ' <<
182  bypass << routing << ' ' <<
183  uri);
184 
185  return true;
186 }
187 
188 bool
190 {
191  // TODO: find core code that parses URLs and extracts various parts
192  // AYJ: most of this is duplicate of URL::parse() in src/url.cc
193 
194  if (!value || !*value) {
195  debugs(3, DBG_CRITICAL, HERE << cfg_filename << ':' << config_lineno << ": " <<
196  "empty adaptation service URI");
197  return false;
198  }
199 
200  uri = value;
201 
202  // extract scheme and use it as the service_configConfig protocol
203  const char *schemeSuffix = "://";
204  const String::size_type schemeEnd = uri.find(schemeSuffix);
205  if (schemeEnd != String::npos)
206  protocol=uri.substr(0,schemeEnd);
207 
208  debugs(3, 5, HERE << cfg_filename << ':' << config_lineno << ": " <<
209  "service protocol is " << protocol);
210 
211  if (protocol.size() == 0)
212  return false;
213 
214  // skip scheme
215  const char *s = uri.termedBuf() + protocol.size() + strlen(schemeSuffix);
216 
217  const char *e;
218 
219  bool have_port = false;
220 
221  int len = 0;
222  if (*s == '[') {
223  const char *t;
224  if ((t = strchr(s, ']')) == NULL)
225  return false;
226 
227  ++s;
228  len = t - s;
229  if ((e = strchr(t, ':')) != NULL) {
230  have_port = true;
231  } else if ((e = strchr(t, '/')) != NULL) {
232  have_port = false;
233  } else {
234  return false;
235  }
236  } else {
237  if ((e = strchr(s, ':')) != NULL) {
238  have_port = true;
239  } else if ((e = strchr(s, '/')) != NULL) {
240  have_port = false;
241  } else {
242  return false;
243  }
244  len = e - s;
245  }
246 
247  host.limitInit(s, len);
248 #if USE_OPENSSL
249  if (secure.sslDomain.isEmpty())
250  secure.sslDomain.assign(host.rawBuf(), host.size());
251 #endif
252  s = e;
253 
254  port = -1;
255  if (have_port) {
256  ++s;
257 
258  if ((e = strchr(s, '/')) != NULL) {
259  char *t;
260  const unsigned long p = strtoul(s, &t, 0);
261 
262  if (p > 65535) // port value is too high
263  return false;
264 
265  port = static_cast<int>(p);
266 
267  if (t != e) // extras after the port
268  return false;
269 
270  s = e;
271 
272  if (s[0] != '/')
273  return false;
274  }
275  }
276 
277  // if no port, the caller may use service_configConfigs or supply the default if neeeded
278 
279  ++s;
280  e = strchr(s, '\0');
281  len = e - s;
282 
283  if (len > 1024) {
284  debugs(3, DBG_CRITICAL, HERE << cfg_filename << ':' << config_lineno << ": " <<
285  "long resource name (>1024), probably wrong");
286  }
287 
288  resource.limitInit(s, len + 1);
289  return true;
290 }
291 
292 bool
293 Adaptation::ServiceConfig::grokBool(bool &var, const char *name, const char *value)
294 {
295  if (!strcmp(value, "0") || !strcmp(value, "off"))
296  var = false;
297  else if (!strcmp(value, "1") || !strcmp(value, "on"))
298  var = true;
299  else {
300  debugs(3, DBG_CRITICAL, HERE << cfg_filename << ':' << config_lineno << ": " <<
301  "wrong value for boolean " << name << "; " <<
302  "'0', '1', 'on', or 'off' expected but got: " << value);
303  return false;
304  }
305 
306  return true;
307 }
308 
309 bool
310 Adaptation::ServiceConfig::grokLong(long &var, const char *name, const char *value)
311 {
312  char *bad = NULL;
313  const long p = strtol(value, &bad, 0);
314  if (p < 0 || bad == value) {
315  debugs(3, DBG_CRITICAL, "ERROR: " << cfg_filename << ':' <<
316  config_lineno << ": " << "wrong value for " << name << "; " <<
317  "a non-negative integer expected but got: " << value);
318  return false;
319  }
320  var = p;
321  return true;
322 }
323 
324 bool
326 {
327  if (strcmp(value, "block") == 0)
328  var = srvBlock;
329  else if (strcmp(value, "bypass") == 0)
330  var = srvBypass;
331  else if (strcmp(value, "wait") == 0)
332  var = srvWait;
333  else if (strcmp(value, "force") == 0)
334  var = srvForce;
335  else {
336  debugs(3, DBG_CRITICAL, "ERROR: " << cfg_filename << ':' <<
337  config_lineno << ": " << "wrong value for on-overload; " <<
338  "'block', 'bypass', 'wait' or 'force' expected but got: " << value);
339  return false;
340  }
341  return true;
342 }
343 
344 bool
345 Adaptation::ServiceConfig::grokExtension(const char *name, const char *value)
346 {
347  // we do not accept extensions by default
348  debugs(3, DBG_CRITICAL, cfg_filename << ':' << config_lineno << ": " <<
349  "ERROR: unknown adaptation service option: " <<
350  name << '=' << value);
351  return false;
352 }
353 
bool grokOnOverload(SrvBehaviour &var, const char *value)
handle on-overload configuration option
static const size_type npos
Definition: SquidString.h:38
bool grokLong(long &var, const char *name, const char *value)
void encrypt(char *nachr, int decr)
Definition: encrypt.c:188
const char * methodStr(Method)
Definition: Elements.cc:15
virtual bool grokExtension(const char *name, const char *value)
handle name=value configuration option with name unknown to Squid
#define DBG_CRITICAL
Definition: Debug.h:44
char * p
Definition: membanger.c:43
#define DBG_PARSE_NOTE(x)
Definition: Debug.h:49
size_type size() const
Definition: SquidString.h:71
const char * methodStr() const
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:123
int config_lineno
#define DBG_IMPORTANT
Definition: Debug.h:45
VectPoint parseVectPoint(const char *buf) const
const char * cfg_filename
char const * termedBuf() const
Definition: SquidString.h:90
bool grokUri(const char *value)
static char * NextToken()
const char * vectPointStr() const
bool grokBool(bool &var, const char *name, const char *value)
interpret parsed values
static int port
Definition: ldap_backend.cc:69
int unsigned int const char *desc STUB void int len
Definition: stub_fd.cc:20
std::ostream & HERE(std::ostream &s)
Definition: Debug.h:147
size_t size_type
Definition: SquidString.h:37
size_t HttpReply *STUB StoreEntry const KeyScope scope const HttpRequestMethod & method
Definition: stub_store.cc:126
int EnableIpv6
Whether IPv6 is supported and type of support.
Definition: tools.h:25
Method parseMethod(const char *buf) const
void const cache_key * key
#define NULL
Definition: types.h:166
#define false
Definition: GnuRegex.c:233
const char * vectPointStr(VectPoint)
Definition: Elements.cc:39

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors