You are viewing a plain text version of this content. The canonical link for it is here.
Posted to github@trafficserver.apache.org by GitBox <gi...@apache.org> on 2021/12/01 19:24:26 UTC

[GitHub] [trafficserver] SolidWallOfCode commented on a change in pull request #8335: stats_over_http c++/remap/ipmap updates

SolidWallOfCode commented on a change in pull request #8335:
URL: https://github.com/apache/trafficserver/pull/8335#discussion_r760503777



##########
File path: plugins/stats_over_http/stats_over_http.cc
##########
@@ -705,250 +718,209 @@ TSPluginInit(int argc, const char *argv[])
   /* Path was not set during load, so the param was not a config file, we also
     have an argument so it must be the path, set it here.  Otherwise if no argument
     then use the default _stats path */
-  if ((config_holder->config != NULL) && (config_holder->config->stats_path == 0) && (argc > 0) &&
+  if ((config_holder->config != NULL) && (config_holder->config->stats_path.empty()) && (argc > 0) &&
       (config_holder->config_path == NULL)) {
-    config_holder->config->stats_path     = TSstrdup(argv[0] + ('/' == argv[0][0] ? 1 : 0));
-    config_holder->config->stats_path_len = strlen(config_holder->config->stats_path);
-  } else if ((config_holder->config != NULL) && (config_holder->config->stats_path == 0)) {
-    config_holder->config->stats_path     = nstr(DEFAULT_URL_PATH);
-    config_holder->config->stats_path_len = strlen(config_holder->config->stats_path);
+    config_holder->config->stats_path = TSstrdup(argv[0] + ('/' == argv[0][0] ? 1 : 0));
+  } else if ((config_holder->config != NULL) && (config_holder->config->stats_path.empty())) {
+    config_holder->config->stats_path = DEFAULT_URL_PATH;
   }
 
   /* Create a continuation with a mutex as there is a shared global structure
      containing the headers to add */
-  main_cont = TSContCreate(stats_origin, NULL);
+  main_cont = TSContCreate(global_stats_origin_wrapper, NULL);
   TSContDataSet(main_cont, (void *)config_holder);
   TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, main_cont);
 
   /* Create continuation for management updates to re-read config file */
   config_cont = TSContCreate(config_handler, TSMutexCreate());
   TSContDataSet(config_cont, (void *)config_holder);
   TSMgmtUpdateRegister(config_cont, PLUGIN_NAME);
-  TSDebug(PLUGIN_NAME, "stats module registered with path %s", config_holder->config->stats_path);
+  TSDebug(PLUGIN_NAME, "stats module registered with path %s", config_holder->config->stats_path.c_str());
 
 done:
   return;
 }
 
-static bool
-is_ip_match(const char *ip, char *ipmask, char mask)
+///////////////////////////////////////////////////////////////////////////////
+// Initialize the plugin as a remap plugin.
+//
+TSReturnCode
+TSRemapInit(TSRemapInterface *api_info, char *errbuf, int errbuf_size)
 {
-  unsigned int j, i, k;
-  char cm;
-  // to be able to set mask to 128
-  unsigned int umask = 0xff & mask;
-
-  for (j = 0, i = 0; ((i + 1) * 8) <= umask; i++) {
-    if (ip[i] != ipmask[i]) {
-      return false;
-    }
-    j += 8;
-  }
-  cm = 0;
-  for (k = 0; j < umask; j++, k++) {
-    cm |= 1 << (7 - k);
+  if (api_info->size < sizeof(TSRemapInterface)) {
+    strncpy(errbuf, "[tsremap_init] - Incorrect size of TSRemapInterface structure", errbuf_size - 1);
+    return TS_ERROR;
   }
 
-  if ((ip[i] & cm) != (ipmask[i] & cm)) {
-    return false;
+  if (api_info->tsremap_version < TSREMAP_VERSION) {
+    snprintf(errbuf, errbuf_size, "[tsremap_init] - Incorrect API version %ld.%ld", api_info->tsremap_version >> 16,
+             (api_info->tsremap_version & 0xffff));
+    return TS_ERROR;
   }
-  return true;
+
+  TSDebug(PLUGIN_NAME, "remap plugin is successfully initialized");
+  return TS_SUCCESS;
 }
 
-static bool
-is_ip_allowed(const config_t *config, const struct sockaddr *addr)
+TSReturnCode
+TSRemapNewInstance(int argc, char *argv[], void **ih, char * /* errbuf */, int /* errbuf_size */)
 {
-  char ip_port_text_buffer[INET6_ADDRSTRLEN];
-  int i;
-  char *ipmask;
-  if (!addr) {
-    return true;
+  config_holder_t *config_holder;
+  config_holder = new_config_holder(argc > 2 ? argv[2] : NULL);
+  *ih           = static_cast<void *>(config_holder);
+  /* Path was not set during load, so the param was not a config file, we also
+  have an argument so it must be the path, set it here.  Otherwise if no argument
+  then use the default _stats path */
+  if ((config_holder->config != NULL) && (config_holder->config->stats_path.empty()) && (argc > 2) &&
+      (config_holder->config_path == NULL)) {
+    config_holder->config->stats_path = TSstrdup(argv[2] + ('/' == argv[2][0] ? 1 : 0));
+  } else if ((config_holder->config != NULL) && (config_holder->config->stats_path.empty())) {
+    config_holder->config->stats_path = DEFAULT_URL_PATH;
   }
 
-  if (addr->sa_family == AF_INET && config->allowIps) {
-    const struct sockaddr_in *addr_in = (struct sockaddr_in *)addr;
-    const char *ip                    = (char *)&addr_in->sin_addr;
+  // Associate our config file with remap.config to be able to initiate reloads
+  if (config_holder->config_path != NULL) {
+    TSMgmtString result;
+    const char *var_name = "proxy.config.url_remap.filename";
+    TSMgmtStringGet(var_name, &result);
+    TSMgmtConfigFileAdd(result, config_holder->config_path);
+    TSDebug(PLUGIN_NAME, "Registered config file %s with remap reload", config_holder->config_path);
+  }
 
-    for (i = 0; i < config->ipCount; i++) {
-      ipmask = config->allowIps + (i * (sizeof(struct in_addr) + 1));
-      if (is_ip_match(ip, ipmask, ipmask[4])) {
-        TSDebug(PLUGIN_NAME, "clientip is %s--> ALLOW", inet_ntop(AF_INET, ip, ip_port_text_buffer, INET6_ADDRSTRLEN));
-        return true;
-      }
-    }
-    TSDebug(PLUGIN_NAME, "clientip is %s--> DENY", inet_ntop(AF_INET, ip, ip_port_text_buffer, INET6_ADDRSTRLEN));
-    return false;
-
-  } else if (addr->sa_family == AF_INET6 && config->allowIps6) {
-    const struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)addr;
-    const char *ip                      = (char *)&addr_in6->sin6_addr;
-
-    for (i = 0; i < config->ip6Count; i++) {
-      ipmask = config->allowIps6 + (i * (sizeof(struct in6_addr) + 1));
-      if (is_ip_match(ip, ipmask, ipmask[sizeof(struct in6_addr)])) {
-        TSDebug(PLUGIN_NAME, "clientip6 is %s--> ALLOW", inet_ntop(AF_INET6, ip, ip_port_text_buffer, INET6_ADDRSTRLEN));
-        return true;
-      }
-    }
-    TSDebug(PLUGIN_NAME, "clientip6 is %s--> DENY", inet_ntop(AF_INET6, ip, ip_port_text_buffer, INET6_ADDRSTRLEN));
-    return false;
+  if (config_holder->config != nullptr) {
+    TSDebug(PLUGIN_NAME, "New remap instance for %s on path %s", PLUGIN_NAME, config_holder->config->stats_path.c_str());
+    return TS_SUCCESS;
+  } else {
+    TSDebug(PLUGIN_NAME, "Failed to create stats_over_http instance, config is null");
+    return TS_ERROR;
   }
-  return true;
 }
 
-static void
-parseIps(config_t *config, char *ipStr)
+void
+TSRemapDeleteInstance(void *ih)
 {
-  char buffer[STR_BUFFER_SIZE];
-  char *p, *tok1, *tok2, *ip;
-  int i, mask;
-  char ip_port_text_buffer[INET_ADDRSTRLEN];
-
-  if (!ipStr) {
-    config->ipCount = 1;
-    ip = config->allowIps = TSmalloc(sizeof(struct in_addr) + 1);
-    inet_pton(AF_INET, DEFAULT_IP, ip);
-    ip[4] = 0;
-    return;
+  if (nullptr != ih) {
+    config_holder_t *const config = static_cast<config_holder_t *>(ih);
+    TSDebug(PLUGIN_NAME, "Freeing config");
+    TSfree(config);
   }
+}
 
-  strcpy(buffer, ipStr);
-  p = buffer;
-  while (strtok_r(p, ", \n", &p)) {
-    config->ipCount++;
+///////////////////////////////////////////////////////////////////////////////
+// Main entry point when used as a remap plugin.
+//
+TSRemapStatus
+TSRemapDoRemap(void *ih, TSHttpTxn rh, TSRemapRequestInfo *rri)
+{
+  if (nullptr != ih) {
+    config_holder_t *const config = static_cast<config_holder_t *>(ih);
+    TSEvent event                 = TS_EVENT_NONE;
+    stats_origin(config->config, event, (void *)rh);
   }
-  if (!config->ipCount) {
-    return;
+  return TSREMAP_NO_REMAP;
+}
+
+static bool
+is_ipmap_allowed(const config_t *config, const struct sockaddr *addr)
+{
+  if (!addr) {
+    return true;
   }
-  config->allowIps = TSmalloc(5 * config->ipCount); // 4 bytes for ip + 1 for bit mask
-  strcpy(buffer, ipStr);
-  p = buffer;
-  i = 0;
-  while ((tok1 = strtok_r(p, ", \n", &p))) {
-    TSDebug(PLUGIN_NAME, "%d) parsing: %s", i + 1, tok1);
-    tok2 = strtok_r(tok1, "/", &tok1);
-    ip   = config->allowIps + ((sizeof(struct in_addr) + 1) * i);
-    if (!inet_pton(AF_INET, tok2, ip)) {
-      TSDebug(PLUGIN_NAME, "%d) skipping: %s", i + 1, tok1);
-      continue;
-    }
 
-    if (tok1 != NULL) {
-      tok2 = strtok_r(tok1, "/", &tok1);
-    }
-    if (!tok2) {
-      mask = 32;
-    } else {
-      mask = atoi(tok2);
-    }
-    ip[4] = mask;
-    TSDebug(PLUGIN_NAME, "%d) adding netmask: %s/%d", i + 1, inet_ntop(AF_INET, ip, ip_port_text_buffer, INET_ADDRSTRLEN), ip[4]);
-    i++;
+  if (config->allow_ip_map.contains(addr, nullptr)) {
+    return true;
   }
+
+  return false;
 }
 static void
-parseIps6(config_t *config, char *ipStr)
+parseIpMap(config_t *config, const char *ipStr)
 {
-  char buffer[STR_BUFFER_SIZE];
-  char *p, *tok1, *tok2, *ip;
-  int i, mask;
-  char ip_port_text_buffer[INET6_ADDRSTRLEN];
-
-  if (!ipStr) {
-    config->ip6Count = 1;
-    ip = config->allowIps6 = TSmalloc(sizeof(struct in6_addr) + 1);
-    inet_pton(AF_INET6, DEFAULT_IP6, ip);
-    ip[sizeof(struct in6_addr)] = 0;
-    return;
+  IpAddr min, max;
+  std::string delimiter = ",";
+  size_t pos_start = 0, pos_end, delimiter_len = delimiter.length();
+  std::string token;
+  std::string ipstring("");
+
+  if (ipStr != 0) {
+    ipstring.assign(ipStr);
   }
 
-  strcpy(buffer, ipStr);
-  p = buffer;
-  while (strtok_r(p, ", \n", &p)) {
-    config->ip6Count++;
-  }
-  if (!config->ip6Count) {
+  // sent null ipstring, fill with default open IPs
+  if (ipStr == nullptr) {
+    ats_ip_range_parse(std::string_view{DEFAULT_IP6}, min, max);
+    config->allow_ip_map.fill(min, max, nullptr);
+    ats_ip_range_parse(std::string_view{DEFAULT_IP}, min, max);
+    config->allow_ip_map.fill(min, max, nullptr);
+    TSDebug(PLUGIN_NAME, "Empty allow settings, setting all IPs in allow list");
     return;
   }
 
-  config->allowIps6 = TSmalloc((sizeof(struct in6_addr) + 1) * config->ip6Count); // 16 bytes for ip + 1 for bit mask
-  strcpy(buffer, ipStr);
-  p = buffer;
-  i = 0;
-  while ((tok1 = strtok_r(p, ", \n", &p))) {
-    TSDebug(PLUGIN_NAME, "%d) parsing: %s", i + 1, tok1);
-    tok2 = strtok_r(tok1, "/", &tok1);
-    ip   = config->allowIps6 + ((sizeof(struct in6_addr) + 1) * i);
-    if (!inet_pton(AF_INET6, tok2, ip)) {
-      TSDebug(PLUGIN_NAME, "%d) skipping: %s", i + 1, tok1);
-      continue;
-    }
-
-    if (tok1 != NULL) {
-      tok2 = strtok_r(tok1, "/", &tok1);
-    }
-
-    if (!tok2) {
-      mask = 128;
-    } else {
-      mask = atoi(tok2);
-    }
-    ip[sizeof(struct in6_addr)] = mask;
-    TSDebug(PLUGIN_NAME, "%d) adding netmask: %s/%d", i + 1, inet_ntop(AF_INET6, ip, ip_port_text_buffer, INET6_ADDRSTRLEN),
-            ip[sizeof(struct in6_addr)]);
-    i++;
+  while ((pos_end = ipstring.find(delimiter, pos_start)) != std::string::npos) {
+    token     = ipstring.substr(pos_start, pos_end - pos_start);
+    pos_start = pos_end + delimiter_len;
+    ats_ip_range_parse(std::string_view{token}, min, max);
+    config->allow_ip_map.fill(min, max, nullptr);
+    TSDebug(PLUGIN_NAME, "Added %s to allow ip list", token.c_str());
   }
+  token = ipstring.substr(pos_start);
+  TSDebug(PLUGIN_NAME, "Added %s to allow ip list", token.c_str());
+  ats_ip_range_parse(std::string_view{token}, min, max);
+  config->allow_ip_map.fill(min, max, nullptr);
 }
 
 static config_t *
-new_config(TSFile fh)
+new_config(std::fstream &fh)
 {
-  char buffer[STR_BUFFER_SIZE];
-  config_t *config       = NULL;
-  config                 = (config_t *)TSmalloc(sizeof(config_t));
-  config->stats_path     = 0;
-  config->stats_path_len = 0;
-  config->allowIps       = 0;
-  config->ipCount        = 0;
-  config->allowIps6      = 0;
-  config->ip6Count       = 0;
-  config->recordTypes    = DEFAULT_RECORD_TYPES;
+  config_t *config    = NULL;
+  config              = new config_t();
+  config->recordTypes = DEFAULT_RECORD_TYPES;
+  config->stats_path  = "";
+  std::string cur_line;
+  IpAddr min, max;
 
   if (!fh) {
     TSDebug(PLUGIN_NAME, "No config file, using defaults");
     return config;
   }
 
-  while (TSfgets(fh, buffer, STR_BUFFER_SIZE - 1)) {
-    if (*buffer == '#') {
+  while (std::getline(fh, cur_line)) {
+    // skip empty lines
+    if (cur_line == "") {
+      continue;
+    }
+    if (cur_line.at(0) == '#') {
       continue; /* # Comments, only at line beginning */
     }
-    char *p = 0;
-    if ((p = strstr(buffer, "path="))) {
-      p += strlen("path=");
-      if (p[0] == '/') {
+
+    size_t p = 0;
+
+    if ((p = cur_line.find("path=") != std::string::npos)) {
+      TSDebug(PLUGIN_NAME, "parsing path");
+      p += strlen("path=") - 1;
+      if (cur_line.at(p + 1) == '/') {
         p++;
       }
-      config->stats_path     = nstr(strtok_r(p, " \n", &p));
-      config->stats_path_len = strlen(config->stats_path);
-    } else if ((p = strstr(buffer, "record_types="))) {
-      p += strlen("record_types=");
-      config->recordTypes = strtol(strtok_r(p, " \n", &p), NULL, 16);
-    } else if ((p = strstr(buffer, "allow_ip="))) {
-      p += strlen("allow_ip=");
-      parseIps(config, p);
-    } else if ((p = strstr(buffer, "allow_ip6="))) {
-      p += strlen("allow_ip6=");
-      parseIps6(config, p);
+      config->stats_path = cur_line.substr(p); // nstr(strtok_r(p, " \n", &p));
+    } else if ((p = cur_line.find("record_types=") != std::string::npos)) {
+      TSDebug(PLUGIN_NAME, "parsing record types");
+      p += strlen("record_types=") - 1;
+      config->recordTypes = strtol(cur_line.substr(p).c_str(), NULL, 16);
+    } else if ((p = cur_line.find("allow_ip=") != std::string::npos)) {

Review comment:
       `((p = cur_line.find("allow_ip=")) != std::string::npos)`




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@trafficserver.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org