00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "ink_platform.h"
00032 #include "ink_defs.h"
00033 #include "ink_time.h"
00034
00035 #include "Main.h"
00036 #include "URL.h"
00037 #include "Tokenizer.h"
00038 #include "ControlBase.h"
00039 #include "MatcherUtils.h"
00040 #include "HTTP.h"
00041 #include "ControlMatcher.h"
00042 #include "HdrUtils.h"
00043 #include "Vec.h"
00044
00045 #include <ts/TsBuffer.h>
00046
00047
00048
00049
00050
00051
00052
00053
00054 # define TS_IP_OCTETS(x) \
00055 reinterpret_cast<unsigned char const*>(&(x))[0], \
00056 reinterpret_cast<unsigned char const*>(&(x))[1], \
00057 reinterpret_cast<unsigned char const*>(&(x))[2], \
00058 reinterpret_cast<unsigned char const*>(&(x))[3]
00059
00060
00061 ControlBase::Modifier::~Modifier() {}
00062 ControlBase::Modifier::Type ControlBase::Modifier::type() const { return MOD_INVALID; }
00063
00064 namespace {
00065
00066 struct TimeMod : public ControlBase::Modifier {
00067 time_t start_time;
00068 time_t end_time;
00069
00070 static char const * const NAME;
00071
00072 virtual Type type() const;
00073 virtual char const * name() const;
00074 virtual bool check(HttpRequestData* req) const;
00075 virtual void print(FILE* f) const;
00076 static TimeMod* make(char * value, char const ** error);
00077 static const char* timeOfDayToSeconds(const char *time_str, time_t * seconds);
00078 };
00079
00080 char const * const TimeMod::NAME = "Time";
00081 ControlBase::Modifier::Type TimeMod::type() const { return MOD_TIME; }
00082 char const * TimeMod::name() const { return NAME; }
00083
00084 void TimeMod::print(FILE* f) const {
00085 fprintf(f, "%s=%ld-%ld ",
00086
00087
00088 this->name(), static_cast<long>(start_time), static_cast<long>(end_time)
00089 );
00090 }
00091 bool TimeMod::check(HttpRequestData* req) const {
00092 struct tm cur_time;
00093 time_t timeOfDay = req->xact_start;
00094
00095 ink_localtime_r(&timeOfDay, &cur_time);
00096 timeOfDay = cur_time.tm_hour*(60 * 60) + cur_time.tm_min*60 + cur_time.tm_sec;
00097 return start_time <= timeOfDay && timeOfDay <= end_time;
00098 }
00099
00100 TimeMod*
00101 TimeMod::make(char * value, char const ** error) {
00102 Tokenizer rangeTok("-");
00103 TimeMod* mod = 0;
00104 TimeMod tmp;
00105 int num_tok;
00106
00107 num_tok = rangeTok.Initialize(value, SHARE_TOKS);
00108 if (num_tok == 1) {
00109 *error = "End time not specified";
00110 } else if (num_tok > 2) {
00111 *error = "Malformed time range";
00112 } else if (
00113 0 == (*error = timeOfDayToSeconds(rangeTok[0], &tmp.start_time))
00114 && 0 == (*error = timeOfDayToSeconds(rangeTok[1], &tmp.end_time))
00115 ) {
00116 mod = new TimeMod(tmp);
00117 }
00118 return mod;
00119 }
00120
00121
00122
00123
00124
00125
00126 const char *
00127 TimeMod::timeOfDayToSeconds(const char *time_str, time_t * seconds) {
00128 int hour = 0;
00129 int min = 0;
00130 int sec = 0;
00131 time_t tmp = 0;
00132
00133
00134 if (sscanf(time_str, "%d:%d:%d", &hour, &min, &sec) != 3) {
00135
00136 if (sscanf(time_str, "%d:%d", &hour, &min) != 2) {
00137 return "Malformed time specified";
00138 }
00139 }
00140
00141 if (!(hour >= 0 && hour <= 23)) return "Illegal hour specification";
00142
00143 tmp = hour * 60;
00144
00145 if (!(min >= 0 && min <= 59)) return "Illegal minute specification";
00146
00147 tmp = (tmp + min) * 60;
00148
00149 if (!(sec >= 0 && sec <= 59)) return "Illegal second specification";
00150
00151 tmp += sec;
00152
00153 *seconds = tmp;
00154 return 0;
00155 }
00156
00157
00158 struct PortMod : public ControlBase::Modifier {
00159 int start_port;
00160 int end_port;
00161
00162 static char const * const NAME;
00163
00164 virtual char const * name() const;
00165 virtual bool check(HttpRequestData* req) const;
00166 virtual void print(FILE* f) const;
00167
00168 static PortMod* make(char* value, char const **error);
00169 };
00170
00171 char const * const PortMod::NAME = "Port";
00172 char const * PortMod::name() const { return NAME; }
00173
00174 void PortMod::print(FILE* f) const {
00175 fprintf(f, "%s=%d-%d ", this->name(), start_port, end_port);
00176 }
00177
00178 bool PortMod::check(HttpRequestData* req) const {
00179 int port = req->hdr->port_get();
00180 return start_port <= port && port <= end_port;
00181 }
00182
00183 PortMod*
00184 PortMod::make(char* value, char const ** error) {
00185 Tokenizer rangeTok("-");
00186 PortMod tmp;
00187 int num_tok = rangeTok.Initialize(value, SHARE_TOKS);
00188
00189 *error = 0;
00190 if (num_tok > 2) {
00191 *error = "Malformed Range";
00192
00193 } else if (sscanf(rangeTok[0], "%d", &tmp.start_port) != 1) {
00194 *error = "Invalid start port";
00195 } else if (num_tok == 2) {
00196
00197 if (sscanf(rangeTok[1], "%d", &tmp.end_port) != 1)
00198 *error = "Invalid end port";
00199 else if (tmp.end_port < tmp.start_port)
00200 *error = "Malformed Range: end port < start port";
00201 } else {
00202 tmp.end_port = tmp.start_port;
00203 }
00204
00205
00206
00207 return *error ? 0 : new PortMod(tmp);
00208 }
00209
00210
00211 struct IPortMod : public ControlBase::Modifier {
00212 int _port;
00213
00214 static char const * const NAME;
00215
00216 IPortMod(int port);
00217
00218 virtual char const * name() const;
00219 virtual bool check(HttpRequestData* req) const;
00220 virtual void print(FILE* f) const;
00221 static IPortMod* make(char* value, char const ** error);
00222 };
00223
00224 char const * const IPortMod::NAME = "IPort";
00225 IPortMod::IPortMod(int port) : _port(port) {}
00226 char const * IPortMod::name() const { return NAME; }
00227
00228 void IPortMod::print(FILE* f) const {
00229 fprintf(f, "%s=%d ", this->name(), _port);
00230 }
00231 bool IPortMod::check(HttpRequestData* req) const {
00232 return req->incoming_port == _port;
00233 }
00234
00235 IPortMod*
00236 IPortMod::make(char* value, char const ** error) {
00237 IPortMod* zret = 0;
00238 int port;
00239
00240 if (sscanf(value, "%u", &port) == 1) {
00241 zret = new IPortMod(port);
00242 } else {
00243 *error = "Invalid incoming port";
00244 }
00245 return zret;
00246 }
00247
00248 struct SrcIPMod : public ControlBase::Modifier {
00249
00250 IpEndpoint start_addr;
00251 IpEndpoint end_addr;
00252
00253 static char const * const NAME;
00254
00255 virtual Type type() const;
00256 virtual char const * name() const;
00257 virtual bool check(HttpRequestData* req) const;
00258 virtual void print(FILE* f) const;
00259 static SrcIPMod* make(char * value, char const ** error);
00260 };
00261
00262 char const * const SrcIPMod::NAME = "SrcIP";
00263 ControlBase::Modifier::Type SrcIPMod::type() const { return MOD_SRC_IP; }
00264 char const * SrcIPMod::name() const { return NAME; }
00265
00266 void SrcIPMod::print(FILE* f) const {
00267 ip_text_buffer b1, b2;
00268 fprintf(f, "%s=%s-%s "
00269 ,this->name()
00270 , ats_ip_ntop(&start_addr.sa, b1, sizeof(b1))
00271 , ats_ip_ntop(&end_addr.sa, b2, sizeof(b2))
00272 );
00273 }
00274 bool SrcIPMod::check(HttpRequestData* req) const {
00275
00276 return ats_ip_addr_cmp(&start_addr, &req->src_ip) <= 0
00277 && ats_ip_addr_cmp(&req->src_ip, &end_addr) <= 0
00278 ;
00279 }
00280 SrcIPMod*
00281 SrcIPMod::make(char * value, char const ** error ) {
00282 SrcIPMod tmp;
00283 SrcIPMod* zret = 0;
00284 *error = ExtractIpRange(value, &tmp.start_addr.sa, &tmp.end_addr.sa);
00285
00286 if (!*error) zret = new SrcIPMod(tmp);
00287 return zret;
00288 }
00289
00290 struct SchemeMod : public ControlBase::Modifier {
00291 int _scheme;
00292
00293 static char const * const NAME;
00294
00295 SchemeMod(int scheme);
00296
00297 virtual Type type() const;
00298 virtual char const * name() const;
00299 virtual bool check(HttpRequestData* req) const;
00300 virtual void print(FILE* f) const;
00301
00302 char const* getWksText() const;
00303
00304 static SchemeMod* make(char * value, char const ** error);
00305 };
00306
00307 char const * const SchemeMod::NAME = "Scheme";
00308
00309 SchemeMod::SchemeMod(int scheme) : _scheme(scheme) {}
00310
00311 ControlBase::Modifier::Type SchemeMod::type() const { return MOD_SCHEME; }
00312 char const * SchemeMod::name() const { return NAME; }
00313 char const *
00314 SchemeMod::getWksText() const {
00315 return hdrtoken_index_to_wks(_scheme);
00316 }
00317
00318 bool SchemeMod::check(HttpRequestData* req) const {
00319 return req->hdr->url_get()->scheme_get_wksidx() == _scheme;
00320 }
00321 void SchemeMod::print(FILE* f) const {
00322 fprintf(f, "%s=%s ", this->name(), hdrtoken_index_to_wks(_scheme));
00323 }
00324 SchemeMod*
00325 SchemeMod::make(char * value, char const ** error) {
00326 SchemeMod* zret = 0;
00327 int scheme = hdrtoken_tokenize(value, strlen(value));
00328 if (scheme < 0) {
00329 *error = "Unknown scheme";
00330 } else {
00331 zret = new SchemeMod(scheme);
00332 }
00333 return zret;
00334 }
00335
00336
00337
00338
00339 struct TextMod : public ControlBase::Modifier {
00340 ts::Buffer text;
00341
00342 TextMod();
00343 ~TextMod();
00344
00345
00346 virtual void print(FILE* f) const;
00347
00348
00349 void set(const char * value);
00350
00351 };
00352
00353 TextMod::TextMod() : text() {}
00354 TextMod::~TextMod() {
00355 free(text.data());
00356 }
00357
00358 void TextMod::print(FILE* f) const {
00359 fprintf(f, "%s=%*s ", this->name(), static_cast<int>(text.size()), text.data());
00360 }
00361
00362 void TextMod::set(const char * value) {
00363 free(this->text.data());
00364 this->text.set(ats_strdup(value), strlen(value));
00365 }
00366
00367 struct MultiTextMod : public ControlBase::Modifier {
00368 Vec<ts::Buffer> text_vec;
00369 MultiTextMod();
00370 ~MultiTextMod();
00371
00372
00373 void set(char * value);
00374
00375
00376 virtual void print(FILE* f) const;
00377 };
00378
00379 MultiTextMod::MultiTextMod() {}
00380 MultiTextMod::~MultiTextMod() {
00381 text_vec.clear();
00382 }
00383
00384 void MultiTextMod::print(FILE* f) const {
00385 for_Vec(ts::Buffer, text_iter, this->text_vec)
00386 fprintf(f, "%s=%*s ", this->name(),static_cast<int>(text_iter.size()),text_iter.data());
00387 }
00388
00389 void MultiTextMod::set(char * value) {
00390 Tokenizer rangeTok(",");
00391 int num_tok = rangeTok.Initialize(value, SHARE_TOKS);
00392 for(int i = 0; i < num_tok; i++){
00393 ts::Buffer text;
00394 text.set(ats_strdup(rangeTok[i]), strlen(rangeTok[i]));
00395 this->text_vec.push_back(text);
00396 }
00397 }
00398
00399
00400 struct MethodMod : public TextMod {
00401 static char const * const NAME;
00402
00403 virtual Type type() const;
00404 virtual char const * name() const;
00405 virtual bool check(HttpRequestData* req) const;
00406
00407 static MethodMod* make(char * value, char const ** error);
00408 };
00409 char const * const MethodMod::NAME = "Method";
00410 ControlBase::Modifier::Type MethodMod::type() const { return MOD_METHOD; }
00411 char const * MethodMod::name() const { return NAME; }
00412 bool MethodMod::check(HttpRequestData* req) const {
00413 int method_len;
00414 char const* method = req->hdr->method_get(&method_len);
00415 return method_len >= static_cast<int>(text.size())
00416 && 0 == strncasecmp(method, text.data(), text.size())
00417 ;
00418 }
00419 MethodMod*
00420 MethodMod::make(char * value, char const **) {
00421 MethodMod* mod = new MethodMod();
00422 mod->set(value);
00423 return mod;
00424 }
00425
00426
00427 struct PrefixMod : public TextMod {
00428 static char const * const NAME;
00429
00430 virtual Type type() const;
00431 virtual char const * name() const;
00432 virtual bool check(HttpRequestData* req) const;
00433 static PrefixMod* make(char * value, char const ** error);
00434 };
00435
00436 char const * const PrefixMod::NAME = "Prefix";
00437 ControlBase::Modifier::Type PrefixMod::type() const { return MOD_PREFIX; }
00438 char const * PrefixMod::name() const { return NAME; }
00439 bool PrefixMod::check(HttpRequestData* req) const {
00440 int path_len;
00441 char const* path = req->hdr->url_get()->path_get(&path_len);
00442 bool zret = path_len >= static_cast<int>(text.size())
00443 && 0 == memcmp(path, text.data(), text.size())
00444 ;
00445
00446
00447
00448
00449
00450
00451 return zret;
00452 }
00453 PrefixMod*
00454 PrefixMod::make(char * value, char const ** ) {
00455 PrefixMod* mod = new PrefixMod();
00456
00457
00458 while ('/' == *value) ++value;
00459 mod->set(value);
00460 return mod;
00461 }
00462
00463
00464 struct SuffixMod : public MultiTextMod {
00465 static char const * const NAME;
00466
00467 virtual Type type() const;
00468 virtual char const * name() const;
00469 virtual bool check(HttpRequestData* req) const;
00470 static SuffixMod* make(char * value, char const ** error);
00471 };
00472 char const * const SuffixMod::NAME = "Suffix";
00473 ControlBase::Modifier::Type SuffixMod::type() const { return MOD_SUFFIX; }
00474 char const * SuffixMod::name() const { return NAME; }
00475 bool SuffixMod::check(HttpRequestData* req) const {
00476 int path_len;
00477 char const* path = req->hdr->url_get()->path_get(&path_len);
00478 if(1 == static_cast<int>(this->text_vec.count()) && 1 == static_cast<int>(this->text_vec[0].size()) && 0 == strcmp(this->text_vec[0].data(),"*"))
00479 return true;
00480 for_Vec(ts::Buffer, text_iter, this->text_vec){
00481 if (path_len >= static_cast<int>(text_iter.size()) && 0 == strncasecmp(path + path_len - text_iter.size(), text_iter.data(), text_iter.size()))
00482 return true;
00483 }
00484 return false;
00485 }
00486 SuffixMod*
00487 SuffixMod::make(char * value, char const ** ) {
00488 SuffixMod* mod = new SuffixMod();
00489 mod->set(value);
00490 return mod;
00491 }
00492
00493
00494 struct TagMod : public TextMod {
00495 static char const * const NAME;
00496
00497 virtual Type type() const;
00498 virtual char const * name() const;
00499 virtual bool check(HttpRequestData* req) const;
00500 static TagMod* make(char * value, char const ** error);
00501 };
00502 char const * const TagMod::NAME = "Tag";
00503 ControlBase::Modifier::Type TagMod::type() const { return MOD_TAG; }
00504 char const * TagMod::name() const { return NAME; }
00505 bool TagMod::check(HttpRequestData* req) const {
00506 return 0 == strcmp(req->tag, text.data());
00507 }
00508 TagMod*
00509 TagMod::make(char * value, char const ** ) {
00510 TagMod* mod = new TagMod();
00511 mod->set(value);
00512 return mod;
00513 }
00514
00515
00516 }
00517
00518 ControlBase::~ControlBase() {
00519 this->clear();
00520 }
00521
00522 void
00523 ControlBase::clear() {
00524 _mods.delete_and_clear();
00525 }
00526
00527
00528
00529 void
00530 ControlBase::Print() {
00531 int n = _mods.length();
00532
00533 if (0 >= n) return;
00534
00535 printf("\t\t\t");
00536 for (intptr_t i = 0; i < n; ++i) {
00537 Modifier* cur_mod = _mods[i];
00538 if (!cur_mod) printf("INVALID ");
00539 else cur_mod->print(stdout);
00540 }
00541 printf("\n");
00542 }
00543
00544 char const *
00545 ControlBase::getSchemeModText() const {
00546 char const* zret = 0;
00547 Modifier* mod = this->findModOfType(Modifier::MOD_SCHEME);
00548 if (mod) zret = static_cast<SchemeMod*>(mod)->getWksText();
00549 return zret;
00550 }
00551
00552 bool
00553 ControlBase::CheckModifiers(HttpRequestData * request_data) {
00554 if (!request_data->hdr) {
00555
00556
00557 return true;
00558 }
00559
00560
00561
00562 if (!request_data->tag && findModOfType(Modifier::MOD_TAG))
00563 return false;
00564
00565 forv_Vec(Modifier, cur_mod, _mods)
00566 if (cur_mod && ! cur_mod->check(request_data)) return false;
00567
00568 return true;
00569 }
00570
00571 enum mod_errors {
00572 ME_UNKNOWN,
00573 ME_PARSE_FAILED,
00574 ME_BAD_MOD,
00575 ME_CALLEE_GENERATED
00576 };
00577
00578 static const char *errorFormats[] = {
00579 "Unknown error parsing modifier",
00580 "Unable to parse modifier",
00581 "Unknown modifier",
00582 "Callee Generated",
00583 };
00584
00585 ControlBase::Modifier*
00586 ControlBase::findModOfType(Modifier::Type t) const {
00587 forv_Vec(Modifier, m, _mods)
00588 if (m && t == m->type()) return m;
00589 return 0;
00590 }
00591
00592 const char *
00593 ControlBase::ProcessModifiers(matcher_line * line_info) {
00594
00595 const char *errBuf = NULL;
00596 mod_errors err = ME_UNKNOWN;
00597
00598 int n_elts = line_info->num_el;
00599
00600
00601 if (0 >= n_elts) return 0;
00602
00603 _mods.clear();
00604 _mods.reserve(n_elts);
00605
00606
00607
00608
00609
00610 for (int i = 0; n_elts && ME_UNKNOWN == err && i < MATCHER_MAX_TOKENS; ++i) {
00611 Modifier* mod = 0;
00612
00613 char * label = line_info->line[0][i];
00614 char * value = line_info->line[1][i];
00615
00616 if (!label) continue;
00617 if (!value) {
00618 err = ME_PARSE_FAILED;
00619 break;
00620 }
00621
00622 if (strcasecmp(label, "port") == 0) {
00623 mod = PortMod::make(value, &errBuf);
00624 } else if (strcasecmp(label, "iport") == 0) {
00625 mod = IPortMod::make(value, &errBuf);
00626 } else if (strcasecmp(label, "scheme") == 0) {
00627 mod = SchemeMod::make(value, &errBuf);
00628 } else if (strcasecmp(label, "method") == 0) {
00629 mod = MethodMod::make(value, &errBuf);
00630 } else if (strcasecmp(label, "prefix") == 0) {
00631 mod = PrefixMod::make(value, &errBuf);
00632 } else if (strcasecmp(label, "suffix") == 0) {
00633 mod = SuffixMod::make(value, &errBuf);
00634 } else if (strcasecmp(label, "src_ip") == 0) {
00635 mod = SrcIPMod::make(value, &errBuf);
00636 } else if (strcasecmp(label, "time") == 0) {
00637 mod = TimeMod::make(value, &errBuf);
00638 } else if (strcasecmp(label, "tag") == 0) {
00639 mod = TagMod::make(value, &errBuf);
00640 } else {
00641 err = ME_BAD_MOD;
00642 }
00643
00644 if (errBuf) err = ME_CALLEE_GENERATED;
00645
00646
00647 if (ME_UNKNOWN == err) {
00648 _mods.push_back(mod);
00649 --n_elts;
00650 } else {
00651 delete mod;
00652 }
00653 }
00654
00655 if (err != ME_UNKNOWN) {
00656 this->clear();
00657 if (err != ME_CALLEE_GENERATED) {
00658 errBuf = errorFormats[err];
00659 }
00660 }
00661
00662 return errBuf;
00663 }