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 
00032 #include "libts.h"      
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 char *
00044 readIntoBuffer(const char *file_path, const char *module_name, int *read_size_ptr)
00045 {
00046 
00047   int fd;
00048   struct stat file_info;
00049   char *file_buf;
00050   int read_size = 0;
00051 
00052   if (read_size_ptr != NULL) {
00053     *read_size_ptr = 0;
00054   }
00055   
00056   
00057   if ((fd = open(file_path, O_RDONLY | _O_ATTRIB_NORMAL)) < 0) {
00058     Error("%s Can not open %s file : %s", module_name, file_path, strerror(errno));
00059     return NULL;
00060   }
00061 
00062   if (fstat(fd, &file_info) < 0) {
00063     Error("%s Can not stat %s file : %s", module_name, file_path, strerror(errno));
00064     close(fd);
00065     return NULL;
00066   }
00067 
00068   if (file_info.st_size < 0) {
00069     Error("%s Can not get correct file size for %s file : %" PRId64 "", module_name, file_path, (int64_t) file_info.st_size);
00070     close(fd);
00071     return NULL;
00072   }
00073   
00074   
00075   
00076   file_buf = (char *)ats_malloc(file_info.st_size + 1);
00077   
00078   file_buf[file_info.st_size] = '\0';
00079 
00080   read_size = (file_info.st_size > 0) ? read(fd, file_buf, file_info.st_size) : 0;
00081 
00082   
00083   if (read_size < 0) {
00084     Error("%s Read of %s file failed : %s", module_name, file_path, strerror(errno));
00085     ats_free(file_buf);
00086     file_buf = NULL;
00087   } else if (read_size < file_info.st_size) {
00088     
00089     
00090     Error("%s Only able to read %d bytes out %d for %s file",
00091           module_name, read_size, (int) file_info.st_size, file_path);
00092     file_buf[read_size] = '\0';
00093   }
00094 
00095   if (file_buf && read_size_ptr) {
00096     *read_size_ptr = read_size;
00097   }
00098 
00099   close(fd);
00100 
00101   return file_buf;
00102 }
00103 
00104 
00105 
00106 
00107 
00108 
00109 int
00110 unescapifyStr(char *buffer)
00111 {
00112   char *read = buffer;
00113   char *write = buffer;
00114   char subStr[3];
00115 
00116   subStr[2] = '\0';
00117   while (*read != '\0') {
00118     if (*read == '%' && *(read + 1) != '\0' && *(read + 2) != '\0') {
00119       subStr[0] = *(++read);
00120       subStr[1] = *(++read);
00121       *write = (char)strtol(subStr, (char **) NULL, 16);
00122       read++;
00123       write++;
00124     } else if (*read == '+') {
00125       *write = ' ';
00126       write++;
00127       read++;
00128     } else {
00129       *write = *read;
00130       write++;
00131       read++;
00132     }
00133   }
00134   *write = '\0';
00135 
00136   return (write - buffer);
00137 }
00138 
00139 char const*
00140 ExtractIpRange(char* match_str, in_addr_t* min, in_addr_t* max) {
00141   IpEndpoint ip_min, ip_max;
00142   char const* zret = ExtractIpRange(match_str, &ip_min.sa, &ip_max.sa);
00143   if (0 == zret) { 
00144     if (ats_is_ip4(&ip_min) && ats_is_ip4(&ip_max)) {
00145       if (min) *min = ntohl(ats_ip4_addr_cast(&ip_min));
00146       if (max) *max = ntohl(ats_ip4_addr_cast(&ip_max));
00147     } else {
00148       zret = "The addresses were not IPv4 addresses.";
00149     }
00150   }
00151   return zret;
00152 }
00153 
00154 
00155 
00156 
00157 
00158 
00159 
00160 
00161 
00162 
00163 
00164 
00165 
00166 
00167 
00168 const char *
00169 ExtractIpRange(char *match_str, sockaddr* addr1, sockaddr* addr2)
00170 {
00171   Tokenizer rangeTok("-/");
00172   bool mask = strchr(match_str, '/') != NULL;
00173   int mask_bits;
00174   int mask_val;
00175   int numToks;
00176   IpEndpoint la1, la2;
00177 
00178   
00179   numToks = rangeTok.Initialize(match_str, SHARE_TOKS);
00180 
00181   if (numToks < 0) {
00182     return "no IP address given";
00183   } else if (numToks > 2) {
00184     return "malformed IP range";
00185   }
00186 
00187   if (0 != ats_ip_pton(rangeTok[0], &la1.sa)) {
00188     return "malformed IP address";
00189   }
00190 
00191   
00192   if (numToks == 2) {
00193 
00194     if (mask) {
00195       if (!ats_is_ip4(&la1)) {
00196         return "Masks supported only for IPv4";
00197       }
00198       
00199       if (sscanf(rangeTok[1], "%d", &mask_bits) != 1) {
00200         return "bad mask specification";
00201       }
00202 
00203       if (!(mask_bits >= 0 && mask_bits <= 32)) {
00204         return "invalid mask specification";
00205       }
00206 
00207       if (mask_bits == 32) {
00208         mask_val = 0;
00209       } else {
00210         mask_val = htonl(0xffffffff >> mask_bits);
00211       }
00212       in_addr_t a = ats_ip4_addr_cast(&la1);
00213       ats_ip4_set(&la2, a | mask_val);
00214       ats_ip4_set(&la1, a & (mask_val ^ 0xffffffff));
00215 
00216     } else {
00217       if (0 != ats_ip_pton(rangeTok[1], &la2)) {
00218         return "malformed ip address at range end";
00219       }
00220     }
00221 
00222     if (1 == ats_ip_addr_cmp(&la1.sa, &la2.sa)) {
00223       return "range start greater than range end";
00224     }
00225 
00226     ats_ip_copy(addr2, &la2);
00227   } else {
00228     ats_ip_copy(addr2, &la1);
00229   }
00230 
00231   ats_ip_copy(addr1, &la1);
00232   return NULL;
00233 }
00234 
00235 
00236 
00237 
00238 
00239 
00240 char *
00241 tokLine(char *buf, char **last, char cont)
00242 {
00243   char *start;
00244   char *cur;
00245   char *prev = NULL;
00246 
00247   if (buf != NULL) {
00248     start = cur = buf;
00249     *last = buf;
00250   } else {
00251     start = cur = (*last) + 1;
00252   }
00253 
00254   while (*cur != '\0') {
00255     if (*cur == '\n') {
00256       if (cont != '\0' && prev != NULL && *prev == cont) {
00257         *prev = ' ';
00258         *cur = ' ';
00259       }
00260       else {
00261         *cur = '\0';
00262         *last = cur;
00263         return start;
00264       }
00265     }
00266     prev = cur++;
00267   }
00268 
00269   
00270   
00271   if (cur > (*last + 1)) {
00272     *last = cur - 1;
00273     return start;
00274   }
00275 
00276   return NULL;
00277 }
00278 
00279 const char *matcher_type_str[] = {
00280   "invalid",
00281   "host",
00282   "domain",
00283   "ip",
00284   "url_regex",
00285   "url",
00286   "host_regex"
00287 };
00288 
00289 
00290 
00291 
00292 
00293 
00294 
00295 
00296 
00297 
00298 
00299 
00300 
00301 
00302 
00303 
00304 
00305 const char *
00306 processDurationString(char *str, int *seconds)
00307 {
00308   char *s = str;
00309   char *current = str;
00310   char unit;
00311   int tmp;
00312   int multiplier;
00313   int result = 0;
00314   int len;
00315 
00316   if (str == NULL) {
00317     return "Missing time";
00318   }
00319 
00320   len = strlen(str);
00321   for (int i = 0; i < len; i++) {
00322     if (!ParseRules::is_digit(*current)) {
00323 
00324       
00325       if (current == s) {
00326         return "Malformed time";
00327       }
00328 
00329       unit = *current;
00330 
00331       switch (unit) {
00332       case 'w':
00333         multiplier = 7 * 24 * 60 * 60;
00334         break;
00335       case 'd':
00336         multiplier = 24 * 60 * 60;
00337         break;
00338       case 'h':
00339         multiplier = 60 * 60;
00340         break;
00341       case 'm':
00342         multiplier = 60;
00343         break;
00344       case 's':
00345         multiplier = 1;
00346         break;
00347       case '-':
00348         return "Negative time not permitted";
00349       default:
00350         return "Invalid time unit specified";
00351       }
00352 
00353       *current = '\0';
00354 
00355       
00356       if (sscanf(s, "%d", &tmp) != 1) {
00357         
00358         
00359         ink_assert(0);
00360         return "Malformed time";
00361       }
00362 
00363       result += (multiplier * tmp);
00364       s = current + 1;
00365 
00366     }
00367     current++;
00368   }
00369 
00370   
00371   if (current != s) {
00372     
00373     if (sscanf(s, "%d", &tmp) != 1) {
00374       
00375       
00376       ink_assert(0);
00377       return "Malformed time";
00378     } else {
00379       result += tmp;
00380     }
00381   }
00382   
00383   if (result < 0) {
00384     return "Time too big";
00385   }
00386 
00387   *seconds = result;
00388   return NULL;
00389 }
00390 
00391 const matcher_tags http_dest_tags = {
00392   "dest_host", "dest_domain", "dest_ip", "url_regex", "url", "host_regex", true
00393 };
00394 
00395 const matcher_tags ip_allow_tags = {
00396   NULL, NULL, "src_ip", NULL, NULL, NULL, false
00397 };
00398 
00399 const matcher_tags socks_server_tags = {
00400   NULL, NULL, "dest_ip", NULL, NULL, NULL, false
00401 };
00402 
00403 
00404 
00405 
00406 
00407 
00408 
00409 
00410 
00411 
00412 const char *
00413 parseConfigLine(char *line, matcher_line *p_line, const matcher_tags * tags)
00414 {
00415   enum pState
00416   {
00417     FIND_LABEL, PARSE_LABEL,
00418     PARSE_VAL, START_PARSE_VAL, CONSUME
00419   };
00420 
00421   pState state = FIND_LABEL;
00422   bool inQuote = false;
00423   char *copyForward = NULL;
00424   char *copyFrom = NULL;
00425   char *s = line;
00426   char *label = NULL;
00427   char *val = NULL;
00428   int num_el = 0;
00429   matcher_type type = MATCH_NONE;
00430 
00431   
00432   memset(p_line, 0, sizeof(matcher_line));
00433 
00434   if (*s == '\0') {
00435     return NULL;
00436   }
00437 
00438   do {
00439 
00440     switch (state) {
00441     case FIND_LABEL:
00442       if (!isspace(*s)) {
00443         state = PARSE_LABEL;
00444         label = s;
00445       }
00446       s++;
00447       break;
00448     case PARSE_LABEL:
00449       if (*s == '=') {
00450         *s = '\0';
00451         state = START_PARSE_VAL;
00452       }
00453       s++;
00454       break;
00455     case START_PARSE_VAL:
00456       
00457       copyForward = NULL;
00458       copyFrom = NULL;
00459 
00460       if (*s == '"') {
00461         inQuote = true;
00462         val = s + 1;
00463       } else if (*s == '\\') {
00464         inQuote = false;
00465         val = s + 1;
00466       } else {
00467         inQuote = false;
00468         val = s;
00469 
00470       }
00471 
00472       if (inQuote == false && (isspace(*s) || *(s + 1) == '\0')) {
00473         state = CONSUME;
00474       } else {
00475         state = PARSE_VAL;
00476       }
00477 
00478       s++;
00479       break;
00480     case PARSE_VAL:
00481       if (inQuote == true) {
00482         if (*s == '\\') {
00483           
00484           
00485           
00486           
00487           
00488           
00489           
00490           
00491 
00492           if (copyForward != NULL) {
00493             
00494             int bytesCopy = s - copyFrom;
00495             memcpy(copyForward, copyFrom, s - copyFrom);
00496             ink_assert(bytesCopy > 0);
00497 
00498             copyForward += bytesCopy;
00499             copyFrom = s + 1;
00500           } else {
00501             copyForward = s;
00502             copyFrom = s + 1;
00503           }
00504 
00505           
00506           s++;
00507 
00508           
00509           
00510           if (*s == '\0') {
00511             break;
00512           }
00513         } else if (*s == '"') {
00514           state = CONSUME;
00515           *s = '\0';
00516         }
00517       } else if ((*s == '\\' && ParseRules::is_digit(*(s + 1)))
00518                  || !ParseRules::is_char(*s)) {
00519         
00520         
00521         
00522         return "Unrecognized encoding scheme";
00523       } else if (isspace(*s)) {
00524         state = CONSUME;
00525         *s = '\0';
00526       }
00527 
00528       s++;
00529 
00530       
00531       
00532       if (*s == '\0') {
00533         state = CONSUME;
00534       }
00535       break;
00536     case CONSUME:
00537       break;
00538     }
00539 
00540     if (state == CONSUME) {
00541 
00542       
00543       
00544       if (copyForward != NULL) {
00545         int toCopy = (s - 1) - copyFrom;
00546         memcpy(copyForward, copyFrom, toCopy);
00547         *(copyForward + toCopy) = '\0';
00548       }
00549 
00550       p_line->line[0][num_el] = label;
00551       p_line->line[1][num_el] = val;
00552       type = MATCH_NONE;
00553 
00554       
00555       if (tags->match_ip && strcasecmp(tags->match_ip, label) == 0) {
00556         type = MATCH_IP;
00557       } else if (tags->match_host && strcasecmp(tags->match_host, label) == 0) {
00558         type = MATCH_HOST;
00559       } else if (tags->match_domain && strcasecmp(tags->match_domain, label) == 0) {
00560         type = MATCH_DOMAIN;
00561       } else if (tags->match_regex && strcasecmp(tags->match_regex, label) == 0) {
00562         type = MATCH_REGEX;
00563       } else if (tags->match_url && strcasecmp(tags->match_url, label) == 0) {
00564         type = MATCH_URL;
00565       } else if (tags->match_host_regex && strcasecmp(tags->match_host_regex, label) == 0) {
00566         type = MATCH_HOST_REGEX;
00567       }
00568       
00569       if (type != MATCH_NONE) {
00570         
00571         if (p_line->type != MATCH_NONE) {
00572           if (tags->dest_error_msg == false) {
00573             return "Muliple Sources Specified";
00574           } else {
00575             return "Muliple Destinations Specified";
00576           }
00577         } else {
00578           p_line->dest_entry = num_el;
00579           p_line->type = type;
00580         }
00581       }
00582       num_el++;
00583 
00584       if (num_el > MATCHER_MAX_TOKENS) {
00585         return "Malformed line: Too many tokens";
00586       }
00587 
00588       state = FIND_LABEL;
00589     }
00590   } while (*s != '\0');
00591 
00592   p_line->num_el = num_el;
00593 
00594   if (state != CONSUME && state != FIND_LABEL) {
00595     return "Malformed entry";
00596   }
00597 
00598   if (!tags->empty() && p_line->type == MATCH_NONE) {
00599     if (tags->dest_error_msg == false) {
00600       return "No source specifier";
00601     } else {
00602       return "No destination specifier";
00603     }
00604   }
00605 
00606   return NULL;
00607 }