REORG: server: move keywords in srv_kws
Move server-keyword hardcoded in parse_server into the srv_kws list of
server.c. Now every server keywords is checked through srv_find_kw. This
has the effect to reduce the size of parse_server. As a side-effect,
common kw list can be reduced.
This change has been made to be able to quickly discard these keywords
in case of a dynamic server.
diff --git a/src/server.c b/src/server.c
index 7c08dd0..9a55d96 100644
--- a/src/server.c
+++ b/src/server.c
@@ -50,16 +50,12 @@
static int srv_apply_lastaddr(struct server *srv, int *err_code);
static void srv_cleanup_connections(struct server *srv);
-/* some keywords that are still being parsed using strcmp() and are not
- * registered anywhere. They are used as suggestions for mistyped words.
+/* extra keywords used as value for other arguments. They are used as
+ * suggestions for mistyped words.
*/
-static const char *common_kw_list[] = {
- "init-addr", "resolvers", "resolve-opts", "resolve-prefer", "ipv4",
- "ipv6", "resolve-net", "weight", "log-proto", "legacy", "octet-count",
- "minconn", "maxconn", "maxqueue", "slowstart", "on-error", "fastinter",
- "fail-check", "sudden-death", "mark-down", "on-marked-down",
- "shutdown-sessions", "on-marked-up", "shutdown-backup-sessions",
- "error-limit", "usesrc",
+static const char *extra_kw_list[] = {
+ "ipv4", "ipv6", "legacy", "octet-count",
+ "fastinter", "fail-check", "sudden-death", "mark-down",
NULL /* must be last */
};
@@ -328,7 +324,7 @@
}
}
- for (extra = common_kw_list; *extra; extra++) {
+ for (extra = extra_kw_list; *extra; extra++) {
make_word_fingerprint(list_sig, *extra);
dist = word_fingerprint_distance(word_sig, list_sig);
if (dist < best_dist) {
@@ -393,6 +389,119 @@
return 0;
}
+/* Parse the "error-limit" server keyword */
+static int srv_parse_error_limit(char **args, int *cur_arg,
+ struct proxy *curproxy, struct server *newsrv, char **err)
+{
+ if (!*args[*cur_arg + 1]) {
+ memprintf(err, "'%s' expects an integer argument.",
+ args[*cur_arg]);
+ return ERR_ALERT | ERR_FATAL;
+ }
+
+ newsrv->consecutive_errors_limit = atoi(args[*cur_arg + 1]);
+
+ if (newsrv->consecutive_errors_limit <= 0) {
+ memprintf(err, "%s has to be > 0.",
+ args[*cur_arg]);
+ return ERR_ALERT | ERR_FATAL;
+ }
+
+ return 0;
+}
+
+/* Parse the "init-addr" server keyword */
+static int srv_parse_init_addr(char **args, int *cur_arg,
+ struct proxy *curproxy, struct server *newsrv, char **err)
+{
+ char *p, *end;
+ int done;
+ struct sockaddr_storage sa;
+
+ newsrv->init_addr_methods = 0;
+ memset(&newsrv->init_addr, 0, sizeof(newsrv->init_addr));
+
+ for (p = args[*cur_arg + 1]; *p; p = end) {
+ /* cut on next comma */
+ for (end = p; *end && *end != ','; end++);
+ if (*end)
+ *(end++) = 0;
+
+ memset(&sa, 0, sizeof(sa));
+ if (strcmp(p, "libc") == 0) {
+ done = srv_append_initaddr(&newsrv->init_addr_methods, SRV_IADDR_LIBC);
+ }
+ else if (strcmp(p, "last") == 0) {
+ done = srv_append_initaddr(&newsrv->init_addr_methods, SRV_IADDR_LAST);
+ }
+ else if (strcmp(p, "none") == 0) {
+ done = srv_append_initaddr(&newsrv->init_addr_methods, SRV_IADDR_NONE);
+ }
+ else if (str2ip2(p, &sa, 0)) {
+ if (is_addr(&newsrv->init_addr)) {
+ memprintf(err, "'%s' : initial address already specified, cannot add '%s'.",
+ args[*cur_arg], p);
+ return ERR_ALERT | ERR_FATAL;
+ }
+ newsrv->init_addr = sa;
+ done = srv_append_initaddr(&newsrv->init_addr_methods, SRV_IADDR_IP);
+ }
+ else {
+ memprintf(err, "'%s' : unknown init-addr method '%s', supported methods are 'libc', 'last', 'none'.",
+ args[*cur_arg], p);
+ return ERR_ALERT | ERR_FATAL;
+ }
+ if (!done) {
+ memprintf(err, "'%s' : too many init-addr methods when trying to add '%s'",
+ args[*cur_arg], p);
+ return ERR_ALERT | ERR_FATAL;
+ }
+ }
+
+ return 0;
+}
+
+/* Parse the "log-proto" server keyword */
+static int srv_parse_log_proto(char **args, int *cur_arg,
+ struct proxy *curproxy, struct server *newsrv, char **err)
+{
+ if (strcmp(args[*cur_arg + 1], "legacy") == 0)
+ newsrv->log_proto = SRV_LOG_PROTO_LEGACY;
+ else if (strcmp(args[*cur_arg + 1], "octet-count") == 0)
+ newsrv->log_proto = SRV_LOG_PROTO_OCTET_COUNTING;
+ else {
+ memprintf(err, "'%s' expects one of 'legacy' or 'octet-count' but got '%s'",
+ args[*cur_arg], args[*cur_arg + 1]);
+ return ERR_ALERT | ERR_FATAL;
+ }
+
+ return 0;
+}
+
+/* Parse the "maxconn" server keyword */
+static int srv_parse_maxconn(char **args, int *cur_arg,
+ struct proxy *curproxy, struct server *newsrv, char **err)
+{
+ newsrv->maxconn = atol(args[*cur_arg + 1]);
+ return 0;
+}
+
+/* Parse the "maxqueue" server keyword */
+static int srv_parse_maxqueue(char **args, int *cur_arg,
+ struct proxy *curproxy, struct server *newsrv, char **err)
+{
+ newsrv->maxqueue = atol(args[*cur_arg + 1]);
+ return 0;
+}
+
+/* Parse the "minconn" server keyword */
+static int srv_parse_minconn(char **args, int *cur_arg,
+ struct proxy *curproxy, struct server *newsrv, char **err)
+{
+ newsrv->minconn = atol(args[*cur_arg + 1]);
+ return 0;
+}
+
static int srv_parse_max_reuse(char **args, int *cur_arg, struct proxy *curproxy, struct server *newsrv, char **err)
{
char *arg;
@@ -690,6 +799,58 @@
return 0;
}
+/* Parse the "on-error" server keyword */
+static int srv_parse_on_error(char **args, int *cur_arg,
+ struct proxy *curproxy, struct server *newsrv, char **err)
+{
+ if (strcmp(args[*cur_arg + 1], "fastinter") == 0)
+ newsrv->onerror = HANA_ONERR_FASTINTER;
+ else if (strcmp(args[*cur_arg + 1], "fail-check") == 0)
+ newsrv->onerror = HANA_ONERR_FAILCHK;
+ else if (strcmp(args[*cur_arg + 1], "sudden-death") == 0)
+ newsrv->onerror = HANA_ONERR_SUDDTH;
+ else if (strcmp(args[*cur_arg + 1], "mark-down") == 0)
+ newsrv->onerror = HANA_ONERR_MARKDWN;
+ else {
+ memprintf(err, "'%s' expects one of 'fastinter', "
+ "'fail-check', 'sudden-death' or 'mark-down' but got '%s'",
+ args[*cur_arg], args[*cur_arg + 1]);
+ return ERR_ALERT | ERR_FATAL;
+ }
+
+ return 0;
+}
+
+/* Parse the "on-marked-down" server keyword */
+static int srv_parse_on_marked_down(char **args, int *cur_arg,
+ struct proxy *curproxy, struct server *newsrv, char **err)
+{
+ if (strcmp(args[*cur_arg + 1], "shutdown-sessions") == 0)
+ newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
+ else {
+ memprintf(err, "'%s' expects 'shutdown-sessions' but got '%s'",
+ args[*cur_arg], args[*cur_arg + 1]);
+ return ERR_ALERT | ERR_FATAL;
+ }
+
+ return 0;
+}
+
+/* Parse the "on-marked-up" server keyword */
+static int srv_parse_on_marked_up(char **args, int *cur_arg,
+ struct proxy *curproxy, struct server *newsrv, char **err)
+{
+ if (strcmp(args[*cur_arg + 1], "shutdown-backup-sessions") == 0)
+ newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
+ else {
+ memprintf(err, "'%s' expects 'shutdown-backup-sessions' but got '%s'",
+ args[*cur_arg], args[*cur_arg + 1]);
+ return ERR_ALERT | ERR_FATAL;
+ }
+
+ return 0;
+}
+
/* Parse the "redir" server keyword */
static int srv_parse_redir(char **args, int *cur_arg,
struct proxy *curproxy, struct server *newsrv, char **err)
@@ -709,6 +870,120 @@
return 0;
}
+/* Parse the "resolvers" server keyword */
+static int srv_parse_resolvers(char **args, int *cur_arg,
+ struct proxy *curproxy, struct server *newsrv, char **err)
+{
+ free(newsrv->resolvers_id);
+ newsrv->resolvers_id = strdup(args[*cur_arg + 1]);
+ return 0;
+}
+
+/* Parse the "resolve-net" server keyword */
+static int srv_parse_resolve_net(char **args, int *cur_arg,
+ struct proxy *curproxy, struct server *newsrv, char **err)
+{
+ char *p, *e;
+ unsigned char mask;
+ struct resolv_options *opt;
+
+ if (!args[*cur_arg + 1] || args[*cur_arg + 1][0] == '\0') {
+ memprintf(err, "'%s' expects a list of networks.",
+ args[*cur_arg]);
+ return ERR_ALERT | ERR_FATAL;
+ }
+
+ opt = &newsrv->resolv_opts;
+
+ /* Split arguments by comma, and convert it from ipv4 or ipv6
+ * string network in in_addr or in6_addr.
+ */
+ p = args[*cur_arg + 1];
+ e = p;
+ while (*p != '\0') {
+ /* If no room available, return error. */
+ if (opt->pref_net_nb >= SRV_MAX_PREF_NET) {
+ memprintf(err, "'%s' exceed %d networks.",
+ args[*cur_arg], SRV_MAX_PREF_NET);
+ return ERR_ALERT | ERR_FATAL;
+ }
+ /* look for end or comma. */
+ while (*e != ',' && *e != '\0')
+ e++;
+ if (*e == ',') {
+ *e = '\0';
+ e++;
+ }
+ if (str2net(p, 0, &opt->pref_net[opt->pref_net_nb].addr.in4,
+ &opt->pref_net[opt->pref_net_nb].mask.in4)) {
+ /* Try to convert input string from ipv4 or ipv6 network. */
+ opt->pref_net[opt->pref_net_nb].family = AF_INET;
+ } else if (str62net(p, &opt->pref_net[opt->pref_net_nb].addr.in6,
+ &mask)) {
+ /* Try to convert input string from ipv6 network. */
+ len2mask6(mask, &opt->pref_net[opt->pref_net_nb].mask.in6);
+ opt->pref_net[opt->pref_net_nb].family = AF_INET6;
+ } else {
+ /* All network conversions fail, return error. */
+ memprintf(err, "'%s' invalid network '%s'.",
+ args[*cur_arg], p);
+ return ERR_ALERT | ERR_FATAL;
+ }
+ opt->pref_net_nb++;
+ p = e;
+ }
+
+ return 0;
+}
+
+/* Parse the "resolve-opts" server keyword */
+static int srv_parse_resolve_opts(char **args, int *cur_arg,
+ struct proxy *curproxy, struct server *newsrv, char **err)
+{
+ char *p, *end;
+
+ for (p = args[*cur_arg + 1]; *p; p = end) {
+ /* cut on next comma */
+ for (end = p; *end && *end != ','; end++);
+ if (*end)
+ *(end++) = 0;
+
+ if (strcmp(p, "allow-dup-ip") == 0) {
+ newsrv->resolv_opts.accept_duplicate_ip = 1;
+ }
+ else if (strcmp(p, "ignore-weight") == 0) {
+ newsrv->resolv_opts.ignore_weight = 1;
+ }
+ else if (strcmp(p, "prevent-dup-ip") == 0) {
+ newsrv->resolv_opts.accept_duplicate_ip = 0;
+ }
+ else {
+ memprintf(err, "'%s' : unknown resolve-opts option '%s', supported methods are 'allow-dup-ip', 'ignore-weight', and 'prevent-dup-ip'.",
+ args[*cur_arg], p);
+ return ERR_ALERT | ERR_FATAL;
+ }
+ }
+
+ return 0;
+}
+
+/* Parse the "resolve-prefer" server keyword */
+static int srv_parse_resolve_prefer(char **args, int *cur_arg,
+ struct proxy *curproxy, struct server *newsrv, char **err)
+{
+ if (strcmp(args[*cur_arg + 1], "ipv4") == 0)
+ newsrv->resolv_opts.family_prio = AF_INET;
+ else if (strcmp(args[*cur_arg + 1], "ipv6") == 0)
+ newsrv->resolv_opts.family_prio = AF_INET6;
+ else {
+ memprintf(err, "'%s' expects either ipv4 or ipv6 as argument.",
+ args[*cur_arg]);
+ return ERR_ALERT | ERR_FATAL;
+ }
+
+ return 0;
+}
+
/* Parse the "send-proxy" server keyword */
static int srv_parse_send_proxy(char **args, int *cur_arg,
struct proxy *curproxy, struct server *newsrv, char **err)
@@ -723,6 +998,33 @@
return srv_enable_pp_flags(newsrv, SRV_PP_V2);
}
+/* Parse the "slowstart" server keyword */
+static int srv_parse_slowstart(char **args, int *cur_arg,
+ struct proxy *curproxy, struct server *newsrv, char **err)
+{
+ /* slowstart is stored in seconds */
+ unsigned int val;
+ const char *time_err = parse_time_err(args[*cur_arg + 1], &val, TIME_UNIT_MS);
+
+ if (time_err == PARSE_TIME_OVER) {
+ memprintf(err, "overflow in argument <%s> to <%s> of server %s, maximum value is 2147483647 ms (~24.8 days).",
+ args[*cur_arg+1], args[*cur_arg], newsrv->id);
+ return ERR_ALERT | ERR_FATAL;
+ }
+ else if (time_err == PARSE_TIME_UNDER) {
+ memprintf(err, "underflow in argument <%s> to <%s> of server %s, minimum non-null value is 1 ms.",
+ args[*cur_arg+1], args[*cur_arg], newsrv->id);
+ return ERR_ALERT | ERR_FATAL;
+ }
+ else if (time_err) {
+ memprintf(err, "unexpected character '%c' in 'slowstart' argument of server %s.",
+ *time_err, newsrv->id);
+ return ERR_ALERT | ERR_FATAL;
+ }
+ newsrv->slowstart = (val + 999) / 1000;
+
+ return 0;
+}
/* Parse the "source" server keyword */
static int srv_parse_source(char **args, int *cur_arg,
@@ -937,6 +1239,30 @@
return 0;
}
+/* parse the "usesrc" server keyword */
+static int srv_parse_usesrc(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
+{
+ memprintf(err, "'%s' only allowed after a '%s' statement.",
+ "usesrc", "source");
+ return ERR_ALERT | ERR_FATAL;
+}
+
+/* parse the "weight" server keyword */
+static int srv_parse_weight(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
+{
+ int w;
+
+ w = atol(args[*cur_arg + 1]);
+ if (w < 0 || w > SRV_UWGHT_MAX) {
+ memprintf(err, "weight of server %s is not within 0 and %d (%d).",
+ newsrv->id, SRV_UWGHT_MAX, w);
+ return ERR_ALERT | ERR_FATAL;
+ }
+ newsrv->uweight = newsrv->iweight = w;
+
+ return 0;
+}
+
/* Shutdown all connections of a server. The caller must pass a termination
* code in <why>, which must be one of SF_ERR_* indicating the reason for the
* shutdown.
@@ -1304,8 +1630,14 @@
{ "cookie", srv_parse_cookie, 1, 1 }, /* Assign a cookie to the server */
{ "disabled", srv_parse_disabled, 0, 1 }, /* Start the server in 'disabled' state */
{ "enabled", srv_parse_enabled, 0, 1 }, /* Start the server in 'enabled' state */
+ { "error-limit", srv_parse_error_limit, 1, 1 }, /* Configure the consecutive count of check failures to consider a server on error */
{ "id", srv_parse_id, 1, 0 }, /* set id# of server */
+ { "init-addr", srv_parse_init_addr, 1, 1 }, /* */
+ { "log-proto", srv_parse_log_proto, 1, 1 }, /* Set the protocol for event messages, only relevant in a ring section */
+ { "maxconn", srv_parse_maxconn, 1, 1 }, /* Set the max number of concurrent connection */
+ { "maxqueue", srv_parse_maxqueue, 1, 1 }, /* Set the max number of connection to put in queue */
{ "max-reuse", srv_parse_max_reuse, 1, 1 }, /* Set the max number of requests on a connection, -1 means unlimited */
+ { "minconn", srv_parse_minconn, 1, 1 }, /* Enable a dynamic maxconn limit */
{ "namespace", srv_parse_namespace, 1, 1 }, /* Namespace the server socket belongs to (if supported) */
{ "no-backup", srv_parse_no_backup, 0, 1 }, /* Flag as non-backup server */
{ "no-send-proxy", srv_parse_no_send_proxy, 0, 1 }, /* Disable use of PROXY V1 protocol */
@@ -1313,19 +1645,29 @@
{ "no-tfo", srv_parse_no_tfo, 0, 1 }, /* Disable use of TCP Fast Open */
{ "non-stick", srv_parse_non_stick, 0, 1 }, /* Disable stick-table persistence */
{ "observe", srv_parse_observe, 1, 1 }, /* Enables health adjusting based on observing communication with the server */
+ { "on-error", srv_parse_on_error, 1, 1 }, /* Configure the action on check failure */
+ { "on-marked-down", srv_parse_on_marked_down, 1, 1 }, /* Configure the action when a server is marked down */
+ { "on-marked-up", srv_parse_on_marked_up, 1, 1 }, /* Configure the action when a server is marked up */
{ "pool-low-conn", srv_parse_pool_low_conn, 1, 1 }, /* Set the min number of orphan idle connecbefore being allowed to pick from other threads */
{ "pool-max-conn", srv_parse_pool_max_conn, 1, 1 }, /* Set the max number of orphan idle connections, -1 means unlimited */
{ "pool-purge-delay", srv_parse_pool_purge_delay, 1, 1 }, /* Set the time before we destroy orphan idle connections, defaults to 1s */
{ "proto", srv_parse_proto, 1, 1 }, /* Set the proto to use for all outgoing connections */
{ "proxy-v2-options", srv_parse_proxy_v2_options, 1, 1 }, /* options for send-proxy-v2 */
{ "redir", srv_parse_redir, 1, 1 }, /* Enable redirection mode */
+ { "resolve-net", srv_parse_resolve_net, 1, 1 }, /* Set the prefered network range for name resolution */
+ { "resolve-opts", srv_parse_resolve_opts, 1, 1 }, /* Set options for name resolution */
+ { "resolve-prefer", srv_parse_resolve_prefer, 1, 1 }, /* Set the prefered family for name resolution */
+ { "resolvers", srv_parse_resolvers, 1, 1 }, /* Configure the resolver to use for name resolution */
{ "send-proxy", srv_parse_send_proxy, 0, 1 }, /* Enforce use of PROXY V1 protocol */
{ "send-proxy-v2", srv_parse_send_proxy_v2, 0, 1 }, /* Enforce use of PROXY V2 protocol */
+ { "slowstart", srv_parse_slowstart, 1, 1 }, /* Set the warm-up timer for a previously failed server */
{ "source", srv_parse_source, -1, 1 }, /* Set the source address to be used to connect to the server */
{ "stick", srv_parse_stick, 0, 1 }, /* Enable stick-table persistence */
{ "tfo", srv_parse_tfo, 0, 1 }, /* enable TCP Fast Open of server */
{ "track", srv_parse_track, 1, 1 }, /* Set the current state of the server, tracking another one */
{ "socks4", srv_parse_socks4, 1, 1 }, /* Set the socks4 proxy of the server*/
+ { "usesrc", srv_parse_usesrc, 0, 1 }, /* safe-guard against usesrc without preceding <source> keyword */
+ { "weight", srv_parse_weight, 1, 1 }, /* Set the load-balancing weight */
{ NULL, NULL, 0 },
}};
@@ -2028,7 +2370,6 @@
const char *err = NULL;
char *errmsg = NULL;
int err_code = 0;
- unsigned val;
char *fqdn = NULL;
if (strcmp(args[0], "server") == 0 ||
@@ -2198,343 +2539,60 @@
}
while (*args[cur_arg]) {
- if (strcmp(args[cur_arg], "init-addr") == 0) {
- char *p, *end;
- int done;
- struct sockaddr_storage sa;
-
- newsrv->init_addr_methods = 0;
- memset(&newsrv->init_addr, 0, sizeof(newsrv->init_addr));
-
- for (p = args[cur_arg + 1]; *p; p = end) {
- /* cut on next comma */
- for (end = p; *end && *end != ','; end++);
- if (*end)
- *(end++) = 0;
-
- memset(&sa, 0, sizeof(sa));
- if (strcmp(p, "libc") == 0) {
- done = srv_append_initaddr(&newsrv->init_addr_methods, SRV_IADDR_LIBC);
- }
- else if (strcmp(p, "last") == 0) {
- done = srv_append_initaddr(&newsrv->init_addr_methods, SRV_IADDR_LAST);
- }
- else if (strcmp(p, "none") == 0) {
- done = srv_append_initaddr(&newsrv->init_addr_methods, SRV_IADDR_NONE);
- }
- else if (str2ip2(p, &sa, 0)) {
- if (is_addr(&newsrv->init_addr)) {
- ha_alert("parsing [%s:%d]: '%s' : initial address already specified, cannot add '%s'.\n",
- file, linenum, args[cur_arg], p);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- newsrv->init_addr = sa;
- done = srv_append_initaddr(&newsrv->init_addr_methods, SRV_IADDR_IP);
- }
- else {
- ha_alert("parsing [%s:%d]: '%s' : unknown init-addr method '%s', supported methods are 'libc', 'last', 'none'.\n",
- file, linenum, args[cur_arg], p);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- if (!done) {
- ha_alert("parsing [%s:%d]: '%s' : too many init-addr methods when trying to add '%s'\n",
- file, linenum, args[cur_arg], p);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- }
- cur_arg += 2;
- }
- else if (strcmp(args[cur_arg], "resolvers") == 0) {
- free(newsrv->resolvers_id);
- newsrv->resolvers_id = strdup(args[cur_arg + 1]);
- cur_arg += 2;
- }
- else if (strcmp(args[cur_arg], "resolve-opts") == 0) {
- char *p, *end;
-
- for (p = args[cur_arg + 1]; *p; p = end) {
- /* cut on next comma */
- for (end = p; *end && *end != ','; end++);
- if (*end)
- *(end++) = 0;
-
- if (strcmp(p, "allow-dup-ip") == 0) {
- newsrv->resolv_opts.accept_duplicate_ip = 1;
- }
- else if (strcmp(p, "ignore-weight") == 0) {
- newsrv->resolv_opts.ignore_weight = 1;
- }
- else if (strcmp(p, "prevent-dup-ip") == 0) {
- newsrv->resolv_opts.accept_duplicate_ip = 0;
- }
- else {
- ha_alert("parsing [%s:%d]: '%s' : unknown resolve-opts option '%s', supported methods are 'allow-dup-ip', 'ignore-weight', and 'prevent-dup-ip'.\n",
- file, linenum, args[cur_arg], p);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- }
-
- cur_arg += 2;
- }
- else if (strcmp(args[cur_arg], "resolve-prefer") == 0) {
- if (strcmp(args[cur_arg + 1], "ipv4") == 0)
- newsrv->resolv_opts.family_prio = AF_INET;
- else if (strcmp(args[cur_arg + 1], "ipv6") == 0)
- newsrv->resolv_opts.family_prio = AF_INET6;
- else {
- ha_alert("parsing [%s:%d]: '%s' expects either ipv4 or ipv6 as argument.\n",
- file, linenum, args[cur_arg]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- cur_arg += 2;
- }
- else if (strcmp(args[cur_arg], "resolve-net") == 0) {
- char *p, *e;
- unsigned char mask;
- struct resolv_options *opt;
-
- if (!args[cur_arg + 1] || args[cur_arg + 1][0] == '\0') {
- ha_alert("parsing [%s:%d]: '%s' expects a list of networks.\n",
- file, linenum, args[cur_arg]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
-
- opt = &newsrv->resolv_opts;
-
- /* Split arguments by comma, and convert it from ipv4 or ipv6
- * string network in in_addr or in6_addr.
- */
- p = args[cur_arg + 1];
- e = p;
- while (*p != '\0') {
- /* If no room available, return error. */
- if (opt->pref_net_nb >= SRV_MAX_PREF_NET) {
- ha_alert("parsing [%s:%d]: '%s' exceed %d networks.\n",
- file, linenum, args[cur_arg], SRV_MAX_PREF_NET);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- /* look for end or comma. */
- while (*e != ',' && *e != '\0')
- e++;
- if (*e == ',') {
- *e = '\0';
- e++;
- }
- if (str2net(p, 0, &opt->pref_net[opt->pref_net_nb].addr.in4,
- &opt->pref_net[opt->pref_net_nb].mask.in4)) {
- /* Try to convert input string from ipv4 or ipv6 network. */
- opt->pref_net[opt->pref_net_nb].family = AF_INET;
- } else if (str62net(p, &opt->pref_net[opt->pref_net_nb].addr.in6,
- &mask)) {
- /* Try to convert input string from ipv6 network. */
- len2mask6(mask, &opt->pref_net[opt->pref_net_nb].mask.in6);
- opt->pref_net[opt->pref_net_nb].family = AF_INET6;
- } else {
- /* All network conversions fail, return error. */
- ha_alert("parsing [%s:%d]: '%s': invalid network '%s'.\n",
- file, linenum, args[cur_arg], p);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- opt->pref_net_nb++;
- p = e;
- }
-
- cur_arg += 2;
- }
- else if (strcmp(args[cur_arg], "weight") == 0) {
- int w;
- w = atol(args[cur_arg + 1]);
- if (w < 0 || w > SRV_UWGHT_MAX) {
- ha_alert("parsing [%s:%d] : weight of server %s is not within 0 and %d (%d).\n",
- file, linenum, newsrv->id, SRV_UWGHT_MAX, w);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- newsrv->uweight = newsrv->iweight = w;
- cur_arg += 2;
- }
- else if (strcmp(args[cur_arg], "log-proto") == 0) {
- if (strcmp(args[cur_arg + 1], "legacy") == 0)
- newsrv->log_proto = SRV_LOG_PROTO_LEGACY;
- else if (strcmp(args[cur_arg + 1], "octet-count") == 0)
- newsrv->log_proto = SRV_LOG_PROTO_OCTET_COUNTING;
- else {
- ha_alert("parsing [%s:%d]: '%s' expects one of 'legacy' or "
- "'octet-count' but got '%s'\n",
- file, linenum, args[cur_arg], args[cur_arg + 1]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- cur_arg += 2;
- }
- else if (strcmp(args[cur_arg], "minconn") == 0) {
- newsrv->minconn = atol(args[cur_arg + 1]);
- cur_arg += 2;
- }
- else if (strcmp(args[cur_arg], "maxconn") == 0) {
- newsrv->maxconn = atol(args[cur_arg + 1]);
- cur_arg += 2;
- }
- else if (strcmp(args[cur_arg], "maxqueue") == 0) {
- newsrv->maxqueue = atol(args[cur_arg + 1]);
- cur_arg += 2;
- }
- else if (strcmp(args[cur_arg], "slowstart") == 0) {
- /* slowstart is stored in seconds */
- const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
+ struct srv_kw *kw;
+ const char *best;
- if (err == PARSE_TIME_OVER) {
- ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to <%s> of server %s, maximum value is 2147483647 ms (~24.8 days).\n",
- file, linenum, args[cur_arg+1], args[cur_arg], newsrv->id);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- else if (err == PARSE_TIME_UNDER) {
- ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to <%s> of server %s, minimum non-null value is 1 ms.\n",
- file, linenum, args[cur_arg+1], args[cur_arg], newsrv->id);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- else if (err) {
- ha_alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
- file, linenum, *err, newsrv->id);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- newsrv->slowstart = (val + 999) / 1000;
- cur_arg += 2;
- }
- else if (strcmp(args[cur_arg], "on-error") == 0) {
- if (strcmp(args[cur_arg + 1], "fastinter") == 0)
- newsrv->onerror = HANA_ONERR_FASTINTER;
- else if (strcmp(args[cur_arg + 1], "fail-check") == 0)
- newsrv->onerror = HANA_ONERR_FAILCHK;
- else if (strcmp(args[cur_arg + 1], "sudden-death") == 0)
- newsrv->onerror = HANA_ONERR_SUDDTH;
- else if (strcmp(args[cur_arg + 1], "mark-down") == 0)
- newsrv->onerror = HANA_ONERR_MARKDWN;
- else {
- ha_alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
- "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
- file, linenum, args[cur_arg], args[cur_arg + 1]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
-
- cur_arg += 2;
- }
- else if (strcmp(args[cur_arg], "on-marked-down") == 0) {
- if (strcmp(args[cur_arg + 1], "shutdown-sessions") == 0)
- newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
- else {
- ha_alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
- file, linenum, args[cur_arg], args[cur_arg + 1]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
+ kw = srv_find_kw(args[cur_arg]);
+ if (kw) {
+ char *err = NULL;
+ int code;
- cur_arg += 2;
- }
- else if (strcmp(args[cur_arg], "on-marked-up") == 0) {
- if (strcmp(args[cur_arg + 1], "shutdown-backup-sessions") == 0)
- newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
- else {
- ha_alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
- file, linenum, args[cur_arg], args[cur_arg + 1]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
-
- cur_arg += 2;
- }
- else if (strcmp(args[cur_arg], "error-limit") == 0) {
- if (!*args[cur_arg + 1]) {
- ha_alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
- file, linenum, args[cur_arg]);
+ if (!kw->parse) {
+ ha_alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
+ file, linenum, args[0], args[1], args[cur_arg]);
+ if (kw->skip != -1)
+ cur_arg += 1 + kw->skip ;
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
- newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
-
- if (newsrv->consecutive_errors_limit <= 0) {
- ha_alert("parsing [%s:%d]: %s has to be > 0.\n",
- file, linenum, args[cur_arg]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
+ if (defsrv && !kw->default_ok) {
+ ha_alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
+ file, linenum, args[0], args[1], args[cur_arg]);
+ if (kw->skip != -1)
+ cur_arg += 1 + kw->skip;
+ err_code |= ERR_ALERT;
+ continue;
}
- cur_arg += 2;
- }
- else if (strcmp(args[cur_arg], "usesrc") == 0) { /* address to use outside: needs "source" first */
- ha_alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
- file, linenum, "usesrc", "source");
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
- else {
- struct srv_kw *kw;
- const char *best;
- kw = srv_find_kw(args[cur_arg]);
- if (kw) {
- char *err = NULL;
- int code;
+ code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
+ err_code |= code;
- if (!kw->parse) {
- ha_alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
- file, linenum, args[0], args[1], args[cur_arg]);
+ if (code) {
+ display_parser_err(file, linenum, args, cur_arg, code, &err);
+ if (code & ERR_FATAL) {
+ free(err);
if (kw->skip != -1)
- cur_arg += 1 + kw->skip ;
- err_code |= ERR_ALERT | ERR_FATAL;
+ cur_arg += 1 + kw->skip;
goto out;
}
-
- if (defsrv && !kw->default_ok) {
- ha_alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
- file, linenum, args[0], args[1], args[cur_arg]);
- if (kw->skip != -1)
- cur_arg += 1 + kw->skip ;
- err_code |= ERR_ALERT;
- continue;
- }
-
- code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
- err_code |= code;
-
- if (code) {
- display_parser_err(file, linenum, args, cur_arg, code, &err);
- if (code & ERR_FATAL) {
- free(err);
- if (kw->skip != -1)
- cur_arg += 1 + kw->skip;
- goto out;
- }
- }
- free(err);
- if (kw->skip != -1)
- cur_arg += 1 + kw->skip;
- continue;
}
+ free(err);
+ if (kw->skip != -1)
+ cur_arg += 1 + kw->skip;
+ continue;
+ }
- best = srv_find_best_kw(args[cur_arg]);
- if (best)
- ha_alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'; did you mean '%s' maybe ?\n",
- file, linenum, args[0], args[1], args[cur_arg], best);
- else
- ha_alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.\n",
- file, linenum, args[0], args[1], args[cur_arg]);
+ best = srv_find_best_kw(args[cur_arg]);
+ if (best)
+ ha_alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'; did you mean '%s' maybe ?\n",
+ file, linenum, args[0], args[1], args[cur_arg], best);
+ else
+ ha_alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.\n",
+ file, linenum, args[0], args[1], args[cur_arg]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
}
if (!defsrv)