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 2020/04/30 16:47:29 UTC

[GitHub] [trafficserver] ezelkow1 commented on a change in pull request #6542: Rework stats over http so that it supports both a config file and the original path parameter

ezelkow1 commented on a change in pull request #6542:
URL: https://github.com/apache/trafficserver/pull/6542#discussion_r418148206



##########
File path: plugins/stats_over_http/stats_over_http.c
##########
@@ -322,13 +380,379 @@ TSPluginInit(int argc, const char *argv[])
   argc -= optind;
   argv += optind;
 
-  if (argc > 0) {
-    url_path = TSstrdup(argv[0] + ('/' == argv[0][0] ? 1 : 0)); /* Skip leading / */
+  config_holder = new_config_holder(argc > 0 ? argv[0] : NULL);
+
+  /* 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) &&
+      (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);
   }
-  url_path_len = strlen(url_path);
 
   /* Create a continuation with a mutex as there is a shared global structure
      containing the headers to add */
-  TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, TSContCreate(stats_origin, TSMutexCreate()));
-  TSDebug(PLUGIN_NAME, "stats module registered");
+  main_cont = TSContCreate(stats_origin, 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);
+
+done:
+  return;
+}
+
+static bool
+is_ip_match(const char *ip, char *ipmask, char mask)
+{
+  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 ((ip[i] & cm) != (ipmask[i] & cm)) {
+    return false;
+  }
+  return true;
+}
+
+static bool
+is_ip_allowed(const config_t *config, const struct sockaddr *addr)
+{
+  char ip_port_text_buffer[INET6_ADDRSTRLEN];
+  int i;
+  char *ipmask;
+  if (!addr) {
+    return true;
+  }
+
+  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;
+
+    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;
+  }
+  return true;
+}
+
+static void
+parseIps(config_t *config, char *ipStr)
+{
+  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;
+  }
+
+  strcpy(buffer, ipStr);
+  p = buffer;
+  while (strtok_r(p, ", \n", &p)) {
+    config->ipCount++;
+  }
+  if (!config->ipCount) {
+    return;
+  }
+  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++;
+  }
+}
+static void
+parseIps6(config_t *config, 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;
+  }
+
+  strcpy(buffer, ipStr);
+  p = buffer;
+  while (strtok_r(p, ", \n", &p)) {
+    config->ip6Count++;
+  }
+  if (!config->ip6Count) {
+    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++;
+  }
+}
+
+static config_t *
+new_config(TSFile 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;
+  //	TSmalloc(6);

Review comment:
       👍 I kept forgetting that when transferring it from our codebase, every time Id see it I kept thinking "I need to get rid of that", and of course never remembered to do it :)




----------------------------------------------------------------
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.

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