[HCHK_STATUS_PROCOK] = { CHK_RES_PASSED, "PROCOK", "External check passed" },
};
+const struct extcheck_env extcheck_envs[EXTCHK_SIZE] = {
+ [EXTCHK_PATH] = { "PATH", EXTCHK_SIZE_EVAL_INIT },
+ [EXTCHK_HAPROXY_PROXY_NAME] = { "HAPROXY_PROXY_NAME", EXTCHK_SIZE_EVAL_INIT },
+ [EXTCHK_HAPROXY_PROXY_ID] = { "HAPROXY_PROXY_ID", EXTCHK_SIZE_EVAL_INIT },
+ [EXTCHK_HAPROXY_PROXY_ADDR] = { "HAPROXY_PROXY_ADDR", EXTCHK_SIZE_EVAL_INIT },
+ [EXTCHK_HAPROXY_PROXY_PORT] = { "HAPROXY_PROXY_PORT", EXTCHK_SIZE_EVAL_INIT },
+ [EXTCHK_HAPROXY_SERVER_NAME] = { "HAPROXY_SERVER_NAME", EXTCHK_SIZE_EVAL_INIT },
+ [EXTCHK_HAPROXY_SERVER_ID] = { "HAPROXY_SERVER_ID", EXTCHK_SIZE_EVAL_INIT },
+ [EXTCHK_HAPROXY_SERVER_ADDR] = { "HAPROXY_SERVER_ADDR", EXTCHK_SIZE_EVAL_INIT },
+ [EXTCHK_HAPROXY_SERVER_PORT] = { "HAPROXY_SERVER_PORT", EXTCHK_SIZE_EVAL_INIT },
+ [EXTCHK_HAPROXY_SERVER_MAXCONN] = { "HAPROXY_SERVER_MAXCONN", EXTCHK_SIZE_EVAL_INIT },
+ [EXTCHK_HAPROXY_SERVER_CURCONN] = { "HAPROXY_SERVER_CURCONN", EXTCHK_SIZE_ULONG },
+};
+
static const struct analyze_status analyze_statuses[HANA_STATUS_SIZE] = { /* 0: ignore, 1: error, 2: OK */
[HANA_STATUS_UNKNOWN] = { "Unknown", { 0, 0 }},
return 0;
}
-#define EXTCHECK_ARG_MAX 5
-#define EXTCHECK_ENV_ROOM 16
-
-#define EXTCHECK_ADD_ENV(check, envname, value, idx) { if (external_check_add_env(check, envname, value, idx)) goto err; }
+/* helper macro to set an environment variable and jump to a specific label on failure. */
+#define EXTCHK_SETENV(check, envidx, value, fail) { if (extchk_setenv(check, envidx, value)) goto fail; }
/*
- * helper function to allocate enough space for new environment variables used
- * by external checks.
+ * helper function to allocate enough memory to store an environment variable.
+ * It will also check that the environment variable is updatable, and silently
+ * fail if not.
*/
-static int external_check_add_env(struct check *check, const char *envname, const char *value, int *idx)
+static int extchk_setenv(struct check *check, int idx, const char *value)
{
int len, ret;
+ char *envname;
+ int vmaxlen;
- if (*idx % EXTCHECK_ENV_ROOM == 0) {
- /* Allocate enough space to store new environment variables */
- char **tmp = realloc(check->envp, (EXTCHECK_ENV_ROOM * ((*idx / EXTCHECK_ENV_ROOM) + 1) + 1) * sizeof(check->envp));
- if (tmp == NULL) {
- Alert("Failed to allocate memory for new environment variables. Aborting\n");
- return 1;
- } else {
- check->envp = tmp;
- }
+ if (idx < 0 || idx >= EXTCHK_SIZE) {
+ Alert("Illegal environment variable index %d. Aborting.\n", idx);
+ return 1;
}
+
+ envname = extcheck_envs[idx].name;
+ vmaxlen = extcheck_envs[idx].vmaxlen;
+
+ /* Check if the environment variable is already set, and silently reject
+ * the update if this one is not updatable. */
+ if ((vmaxlen == EXTCHK_SIZE_EVAL_INIT) && (check->envp[idx]))
+ return 0;
+
/* Instead of sending NOT_USED, sending an empty value is preferable */
if (strcmp(value, "NOT_USED") == 0) {
value = "";
}
- len = strlen(envname) + strlen(value) + 1;
- check->envp[*idx] = malloc(len + 1);
- check->envp[*idx + 1] = NULL;
- if (!check->envp[*idx]) {
+
+ len = strlen(envname) + 1;
+ if (vmaxlen == EXTCHK_SIZE_EVAL_INIT)
+ len += strlen(value);
+ else
+ len += vmaxlen;
+
+ if (!check->envp[idx])
+ check->envp[idx] = malloc(len + 1);
+
+ if (!check->envp[idx]) {
Alert("Failed to allocate memory for the environment variable '%s'. Aborting.\n", envname);
return 1;
}
- ret = snprintf(check->envp[*idx], len + 1, "%s=%s", envname, value);
+ ret = snprintf(check->envp[idx], len + 1, "%s=%s", envname, value);
if (ret < 0) {
Alert("Failed to store the environment variable '%s'. Reason : %s. Aborting.\n", envname, strerror(errno));
return 1;
}
- else if (ret != len) {
+ else if (ret > len) {
Alert("Environment variable '%s' was truncated. Aborting.\n", envname);
return 1;
}
- (*idx)++;
return 0;
}
struct proxy *px = s->proxy;
struct listener *listener = NULL, *l;
int i;
- int envidx = 0;
const char *path = px->check_path ? px->check_path : DEF_CHECK_PATH;
char buf[256];
}
check->curpid = NULL;
- check->envp = NULL;
+ check->envp = calloc((EXTCHK_SIZE + 1), sizeof(char *));
+ if (!check->envp) {
+ Alert("Failed to allocate memory for environment variables. Aborting\n");
+ goto err;
+ }
- check->argv = calloc(EXTCHECK_ARG_MAX + 1, sizeof(check->argv));
- if (!check->argv)
+ check->argv = calloc(6, sizeof(char *));
+ if (!check->argv) {
+ Alert("Starting [%s:%s] check: out of memory.\n", px->id, s->id);
goto err;
+ }
check->argv[0] = px->check_command;
check->argv[2] = strdup("NOT_USED");
}
else {
+ Alert("Starting [%s:%s] check: unsupported address family.\n", px->id, s->id);
goto err;
}
port_to_str(&s->addr, buf, sizeof(buf));
check->argv[4] = strdup(buf);
- for (i = 0; i < 5; i++)
- if (!check->argv[i])
+ for (i = 0; i < 5; i++) {
+ if (!check->argv[i]) {
+ Alert("Starting [%s:%s] check: out of memory.\n", px->id, s->id);
goto err;
+ }
+ }
- EXTCHECK_ADD_ENV(check, "PATH", path, &envidx);
+ EXTCHK_SETENV(check, EXTCHK_PATH, path, err);
/* Add proxy environment variables */
- EXTCHECK_ADD_ENV(check, "HAPROXY_PROXY_NAME", px->id, &envidx);
- EXTCHECK_ADD_ENV(check, "HAPROXY_PROXY_ID", ultoa_r(px->uuid, buf, sizeof(buf)), &envidx);
- EXTCHECK_ADD_ENV(check, "HAPROXY_PROXY_ADDR", check->argv[1], &envidx);
- EXTCHECK_ADD_ENV(check, "HAPROXY_PROXY_PORT", check->argv[2], &envidx);
+ EXTCHK_SETENV(check, EXTCHK_HAPROXY_PROXY_NAME, px->id, err);
+ EXTCHK_SETENV(check, EXTCHK_HAPROXY_PROXY_ID, ultoa_r(px->uuid, buf, sizeof(buf)), err);
+ EXTCHK_SETENV(check, EXTCHK_HAPROXY_PROXY_ADDR, check->argv[1], err);
+ EXTCHK_SETENV(check, EXTCHK_HAPROXY_PROXY_PORT, check->argv[2], err);
/* Add server environment variables */
- EXTCHECK_ADD_ENV(check, "HAPROXY_SERVER_NAME", s->id, &envidx);
- EXTCHECK_ADD_ENV(check, "HAPROXY_SERVER_ID", ultoa_r(s->puid, buf, sizeof(buf)), &envidx);
- EXTCHECK_ADD_ENV(check, "HAPROXY_SERVER_ADDR", check->argv[3], &envidx);
- EXTCHECK_ADD_ENV(check, "HAPROXY_SERVER_PORT", check->argv[4], &envidx);
- EXTCHECK_ADD_ENV(check, "HAPROXY_SERVER_MAXCONN", ultoa_r(s->maxconn, buf, sizeof(buf)), &envidx);
- EXTCHECK_ADD_ENV(check, "HAPROXY_SERVER_CURCONN", ultoa_r(s->cur_sess, buf, sizeof(buf)), &envidx);
+ EXTCHK_SETENV(check, EXTCHK_HAPROXY_SERVER_NAME, s->id, err);
+ EXTCHK_SETENV(check, EXTCHK_HAPROXY_SERVER_ID, ultoa_r(s->puid, buf, sizeof(buf)), err);
+ EXTCHK_SETENV(check, EXTCHK_HAPROXY_SERVER_ADDR, check->argv[3], err);
+ EXTCHK_SETENV(check, EXTCHK_HAPROXY_SERVER_PORT, check->argv[4], err);
+ EXTCHK_SETENV(check, EXTCHK_HAPROXY_SERVER_MAXCONN, ultoa_r(s->maxconn, buf, sizeof(buf)), err);
+ EXTCHK_SETENV(check, EXTCHK_HAPROXY_SERVER_CURCONN, ultoa_r(s->cur_sess, buf, sizeof(buf)), err);
+
+ /* Ensure that we don't leave any hole in check->envp */
+ for (i = 0; i < EXTCHK_SIZE; i++)
+ if (!check->envp[i])
+ EXTCHK_SETENV(check, i, "", err);
return 1;
err:
if (check->envp) {
- for (i = 0; i < envidx; i++)
+ for (i = 0; i < EXTCHK_SIZE; i++)
free(check->envp[i]);
free(check->envp);
check->envp = NULL;
*/
static int connect_proc_chk(struct task *t)
{
+ char buf[256];
struct check *check = t->context;
struct server *s = check->server;
struct proxy *px = s->proxy;
/* Child */
extern char **environ;
environ = check->envp;
+ extchk_setenv(check, EXTCHK_HAPROXY_SERVER_CURCONN, ultoa_r(s->cur_sess, buf, sizeof(buf)));
execvp(px->check_command, check->argv);
Alert("Failed to exec process for external health check: %s. Aborting.\n",
strerror(errno));