From: Amaury Denoyelle Date: Mon, 8 Mar 2021 16:08:01 +0000 (+0100) Subject: MINOR: server: prepare parsing for dynamic servers X-Git-Tag: v2.4-dev13~16 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=76e10e78bb213060976a39effc40caef546b4974;p=thirdparty%2Fhaproxy.git MINOR: server: prepare parsing for dynamic servers Prepare the server parsing API to support dynamic servers. - define a new parsing flag to be used for dynamic servers - each keyword contains a new field dynamic_ok to indicate if it can be used for a dynamic server. For now, no keyword are supported. - do not copy settings from the default server for a new dynamic server. - a dynamic server is created in a maintenance mode and requires an explicit 'enable server' command. - a new server flag named SRV_F_DYNAMIC is created. This flag is set for all servers created at runtime. It might be useful later, for example to know if a server can be purged. --- diff --git a/include/haproxy/server-t.h b/include/haproxy/server-t.h index 647cdae3db..714e248725 100644 --- a/include/haproxy/server-t.h +++ b/include/haproxy/server-t.h @@ -148,6 +148,7 @@ enum srv_initaddr { #define SRV_F_FASTOPEN 0x0200 /* Use TCP Fast Open to connect to server */ #define SRV_F_SOCKS4_PROXY 0x0400 /* this server uses SOCKS4 proxy */ #define SRV_F_NO_RESOLUTION 0x0800 /* disable runtime DNS resolution on this server */ +#define SRV_F_DYNAMIC 0x1000 /* dynamic server instantiated at runtime */ /* configured server options for send-proxy (server->pp_opts) */ #define SRV_PP_V1 0x0001 /* proxy protocol version 1 */ @@ -418,6 +419,7 @@ struct srv_kw { int (*parse)(char **args, int *cur_arg, struct proxy *px, struct server *srv, char **err); int skip; /* nb min of args to skip, for use when kw is not handled */ int default_ok; /* non-zero if kw is supported in default-server section */ + int dynamic_ok; /* non-zero if kw is supported in add server cli command */ }; /* @@ -436,7 +438,8 @@ struct srv_kw_list { #define SRV_PARSE_TEMPLATE 0x02 /* 'server-template' keyword */ #define SRV_PARSE_IN_PEER_SECTION 0x04 /* keyword in a peer section */ #define SRV_PARSE_PARSE_ADDR 0x08 /* required to parse the server address in the second argument */ -#define SRV_PARSE_INITIAL_RESOLVE 0x10 /* resolve immediately the fqdn to an ip address */ +#define SRV_PARSE_DYNAMIC 0x10 /* dynamic server created at runtime with cli */ +#define SRV_PARSE_INITIAL_RESOLVE 0x20 /* resolve immediately the fqdn to an ip address */ #endif /* _HAPROXY_SERVER_T_H */ diff --git a/src/cfgparse-ssl.c b/src/cfgparse-ssl.c index 9ac3702e49..4f05ce1c58 100644 --- a/src/cfgparse-ssl.c +++ b/src/cfgparse-ssl.c @@ -1808,45 +1808,45 @@ INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws); * not enabled. */ static struct srv_kw_list srv_kws = { "SSL", { }, { - { "allow-0rtt", srv_parse_allow_0rtt, 0, 1 }, /* Allow using early data on this server */ - { "alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN supported protocols */ - { "ca-file", srv_parse_ca_file, 1, 1 }, /* set CAfile to process verify server cert */ - { "check-alpn", srv_parse_alpn, 1, 1 }, /* Set ALPN used for checks */ - { "check-sni", srv_parse_check_sni, 1, 1 }, /* set SNI */ - { "check-ssl", srv_parse_check_ssl, 0, 1 }, /* enable SSL for health checks */ - { "ciphers", srv_parse_ciphers, 1, 1 }, /* select the cipher suite */ + { "allow-0rtt", srv_parse_allow_0rtt, 0, 1, 0 }, /* Allow using early data on this server */ + { "alpn", srv_parse_alpn, 1, 1, 0 }, /* Set ALPN supported protocols */ + { "ca-file", srv_parse_ca_file, 1, 1, 0 }, /* set CAfile to process verify server cert */ + { "check-alpn", srv_parse_alpn, 1, 1, 0 }, /* Set ALPN used for checks */ + { "check-sni", srv_parse_check_sni, 1, 1, 0 }, /* set SNI */ + { "check-ssl", srv_parse_check_ssl, 0, 1, 0 }, /* enable SSL for health checks */ + { "ciphers", srv_parse_ciphers, 1, 1, 0 }, /* select the cipher suite */ #ifdef HAVE_SSL_CTX_SET_CIPHERSUITES - { "ciphersuites", srv_parse_ciphersuites, 1, 1 }, /* select the cipher suite */ + { "ciphersuites", srv_parse_ciphersuites, 1, 1, 0 }, /* select the cipher suite */ #endif - { "crl-file", srv_parse_crl_file, 1, 1 }, /* set certificate revocation list file use on server cert verify */ - { "crt", srv_parse_crt, 1, 1 }, /* set client certificate */ - { "force-sslv3", srv_parse_tls_method_options, 0, 1 }, /* force SSLv3 */ - { "force-tlsv10", srv_parse_tls_method_options, 0, 1 }, /* force TLSv10 */ - { "force-tlsv11", srv_parse_tls_method_options, 0, 1 }, /* force TLSv11 */ - { "force-tlsv12", srv_parse_tls_method_options, 0, 1 }, /* force TLSv12 */ - { "force-tlsv13", srv_parse_tls_method_options, 0, 1 }, /* force TLSv13 */ - { "no-check-ssl", srv_parse_no_check_ssl, 0, 1 }, /* disable SSL for health checks */ - { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1 }, /* do not send PROXY protocol header v2 with SSL info */ - { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1 }, /* do not send PROXY protocol header v2 with CN */ - { "no-ssl", srv_parse_no_ssl, 0, 1 }, /* disable SSL processing */ - { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1 }, /* disable session reuse */ - { "no-sslv3", srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */ - { "no-tlsv10", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv10 */ - { "no-tlsv11", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv11 */ - { "no-tlsv12", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv12 */ - { "no-tlsv13", srv_parse_tls_method_options, 0, 0 }, /* disable TLSv13 */ - { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */ - { "npn", srv_parse_npn, 1, 1 }, /* Set NPN supported protocols */ - { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */ - { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */ - { "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */ - { "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */ - { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1 }, /* minimum version */ - { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1 }, /* maximum version */ - { "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */ - { "tls-tickets", srv_parse_tls_tickets, 0, 1 }, /* enable session resumption tickets */ - { "verify", srv_parse_verify, 1, 1 }, /* set SSL verify method */ - { "verifyhost", srv_parse_verifyhost, 1, 1 }, /* require that SSL cert verifies for hostname */ + { "crl-file", srv_parse_crl_file, 1, 1, 0 }, /* set certificate revocation list file use on server cert verify */ + { "crt", srv_parse_crt, 1, 1, 0 }, /* set client certificate */ + { "force-sslv3", srv_parse_tls_method_options, 0, 1, 0 }, /* force SSLv3 */ + { "force-tlsv10", srv_parse_tls_method_options, 0, 1, 0 }, /* force TLSv10 */ + { "force-tlsv11", srv_parse_tls_method_options, 0, 1, 0 }, /* force TLSv11 */ + { "force-tlsv12", srv_parse_tls_method_options, 0, 1, 0 }, /* force TLSv12 */ + { "force-tlsv13", srv_parse_tls_method_options, 0, 1, 0 }, /* force TLSv13 */ + { "no-check-ssl", srv_parse_no_check_ssl, 0, 1, 0 }, /* disable SSL for health checks */ + { "no-send-proxy-v2-ssl", srv_parse_no_send_proxy_ssl, 0, 1, 0 }, /* do not send PROXY protocol header v2 with SSL info */ + { "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn, 0, 1, 0 }, /* do not send PROXY protocol header v2 with CN */ + { "no-ssl", srv_parse_no_ssl, 0, 1, 0 }, /* disable SSL processing */ + { "no-ssl-reuse", srv_parse_no_ssl_reuse, 0, 1, 0 }, /* disable session reuse */ + { "no-sslv3", srv_parse_tls_method_options, 0, 0, 0 }, /* disable SSLv3 */ + { "no-tlsv10", srv_parse_tls_method_options, 0, 0, 0 }, /* disable TLSv10 */ + { "no-tlsv11", srv_parse_tls_method_options, 0, 0, 0 }, /* disable TLSv11 */ + { "no-tlsv12", srv_parse_tls_method_options, 0, 0, 0 }, /* disable TLSv12 */ + { "no-tlsv13", srv_parse_tls_method_options, 0, 0, 0 }, /* disable TLSv13 */ + { "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1, 0 }, /* disable session resumption tickets */ + { "npn", srv_parse_npn, 1, 1, 0 }, /* Set NPN supported protocols */ + { "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1, 0 }, /* send PROXY protocol header v2 with SSL info */ + { "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1, 0 }, /* send PROXY protocol header v2 with CN */ + { "sni", srv_parse_sni, 1, 1, 0 }, /* send SNI extension */ + { "ssl", srv_parse_ssl, 0, 1, 0 }, /* enable SSL processing */ + { "ssl-min-ver", srv_parse_tls_method_minmax, 1, 1, 0 }, /* minimum version */ + { "ssl-max-ver", srv_parse_tls_method_minmax, 1, 1, 0 }, /* maximum version */ + { "ssl-reuse", srv_parse_ssl_reuse, 0, 1, 0 }, /* enable session reuse */ + { "tls-tickets", srv_parse_tls_tickets, 0, 1, 0 }, /* enable session resumption tickets */ + { "verify", srv_parse_verify, 1, 1, 0 }, /* set SSL verify method */ + { "verifyhost", srv_parse_verifyhost, 1, 1, 0 }, /* require that SSL cert verifies for hostname */ { NULL, NULL, 0, 0 }, }}; diff --git a/src/cfgparse-tcp.c b/src/cfgparse-tcp.c index e7868e6bf2..a15a110ef5 100644 --- a/src/cfgparse-tcp.c +++ b/src/cfgparse-tcp.c @@ -282,7 +282,7 @@ INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws); static struct srv_kw_list srv_kws = { "TCP", { }, { #ifdef TCP_USER_TIMEOUT - { "tcp-ut", srv_parse_tcp_ut, 1, 1 }, /* set TCP user timeout on server */ + { "tcp-ut", srv_parse_tcp_ut, 1, 1, 0 }, /* set TCP user timeout on server */ #endif { NULL, NULL, 0 }, }}; diff --git a/src/check.c b/src/check.c index 2642d584a6..c32e940c3a 100644 --- a/src/check.c +++ b/src/check.c @@ -2083,25 +2083,25 @@ static int srv_parse_check_port(char **args, int *cur_arg, struct proxy *curpx, } static struct srv_kw_list srv_kws = { "CHK", { }, { - { "addr", srv_parse_addr, 1, 1 }, /* IP address to send health to or to probe from agent-check */ - { "agent-addr", srv_parse_agent_addr, 1, 1 }, /* Enable an auxiliary agent check */ - { "agent-check", srv_parse_agent_check, 0, 1 }, /* Enable agent checks */ - { "agent-inter", srv_parse_agent_inter, 1, 1 }, /* Set the interval between two agent checks */ - { "agent-port", srv_parse_agent_port, 1, 1 }, /* Set the TCP port used for agent checks. */ - { "agent-send", srv_parse_agent_send, 1, 1 }, /* Set string to send to agent. */ - { "check", srv_parse_check, 0, 1 }, /* Enable health checks */ - { "check-proto", srv_parse_check_proto, 1, 1 }, /* Set the mux protocol for health checks */ - { "check-send-proxy", srv_parse_check_send_proxy, 0, 1 }, /* Enable PROXY protocol for health checks */ - { "check-via-socks4", srv_parse_check_via_socks4, 0, 1 }, /* Enable socks4 proxy for health checks */ - { "no-agent-check", srv_parse_no_agent_check, 0, 1 }, /* Do not enable any auxiliary agent check */ - { "no-check", srv_parse_no_check, 0, 1 }, /* Disable health checks */ - { "no-check-send-proxy", srv_parse_no_check_send_proxy, 0, 1 }, /* Disable PROXY protocol for health checks */ - { "rise", srv_parse_check_rise, 1, 1 }, /* Set rise value for health checks */ - { "fall", srv_parse_check_fall, 1, 1 }, /* Set fall value for health checks */ - { "inter", srv_parse_check_inter, 1, 1 }, /* Set inter value for health checks */ - { "fastinter", srv_parse_check_fastinter, 1, 1 }, /* Set fastinter value for health checks */ - { "downinter", srv_parse_check_downinter, 1, 1 }, /* Set downinter value for health checks */ - { "port", srv_parse_check_port, 1, 1 }, /* Set the TCP port used for health checks. */ + { "addr", srv_parse_addr, 1, 1, 0 }, /* IP address to send health to or to probe from agent-check */ + { "agent-addr", srv_parse_agent_addr, 1, 1, 0 }, /* Enable an auxiliary agent check */ + { "agent-check", srv_parse_agent_check, 0, 1, 0 }, /* Enable agent checks */ + { "agent-inter", srv_parse_agent_inter, 1, 1, 0 }, /* Set the interval between two agent checks */ + { "agent-port", srv_parse_agent_port, 1, 1, 0 }, /* Set the TCP port used for agent checks. */ + { "agent-send", srv_parse_agent_send, 1, 1, 0 }, /* Set string to send to agent. */ + { "check", srv_parse_check, 0, 1, 0 }, /* Enable health checks */ + { "check-proto", srv_parse_check_proto, 1, 1, 0 }, /* Set the mux protocol for health checks */ + { "check-send-proxy", srv_parse_check_send_proxy, 0, 1, 0 }, /* Enable PROXY protocol for health checks */ + { "check-via-socks4", srv_parse_check_via_socks4, 0, 1, 0 }, /* Enable socks4 proxy for health checks */ + { "no-agent-check", srv_parse_no_agent_check, 0, 1, 0 }, /* Do not enable any auxiliary agent check */ + { "no-check", srv_parse_no_check, 0, 1, 0 }, /* Disable health checks */ + { "no-check-send-proxy", srv_parse_no_check_send_proxy, 0, 1, 0 }, /* Disable PROXY protocol for health checks */ + { "rise", srv_parse_check_rise, 1, 1, 0 }, /* Set rise value for health checks */ + { "fall", srv_parse_check_fall, 1, 1, 0 }, /* Set fall value for health checks */ + { "inter", srv_parse_check_inter, 1, 1, 0 }, /* Set inter value for health checks */ + { "fastinter", srv_parse_check_fastinter, 1, 1, 0 }, /* Set fastinter value for health checks */ + { "downinter", srv_parse_check_downinter, 1, 1, 0 }, /* Set downinter value for health checks */ + { "port", srv_parse_check_port, 1, 1, 0 }, /* Set the TCP port used for health checks. */ { NULL, NULL, 0 }, }}; diff --git a/src/server.c b/src/server.c index 3c26243f0c..ec9e6e6911 100644 --- a/src/server.c +++ b/src/server.c @@ -1626,48 +1626,48 @@ void srv_compute_all_admin_states(struct proxy *px) * Note: -1 as ->skip value means that the number of arguments are variable. */ static struct srv_kw_list srv_kws = { "ALL", { }, { - { "backup", srv_parse_backup, 0, 1 }, /* Flag as backup server */ - { "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 */ - { "no-send-proxy-v2", srv_parse_no_send_proxy_v2, 0, 1 }, /* Disable use of PROXY V2 protocol */ - { "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 keyword */ - { "weight", srv_parse_weight, 1, 1 }, /* Set the load-balancing weight */ + { "backup", srv_parse_backup, 0, 1, 0 }, /* Flag as backup server */ + { "cookie", srv_parse_cookie, 1, 1, 0 }, /* Assign a cookie to the server */ + { "disabled", srv_parse_disabled, 0, 1, 0 }, /* Start the server in 'disabled' state */ + { "enabled", srv_parse_enabled, 0, 1, 0 }, /* Start the server in 'enabled' state */ + { "error-limit", srv_parse_error_limit, 1, 1, 0 }, /* Configure the consecutive count of check failures to consider a server on error */ + { "id", srv_parse_id, 1, 0, 0 }, /* set id# of server */ + { "init-addr", srv_parse_init_addr, 1, 1, 0 }, /* */ + { "log-proto", srv_parse_log_proto, 1, 1, 0 }, /* Set the protocol for event messages, only relevant in a ring section */ + { "maxconn", srv_parse_maxconn, 1, 1, 0 }, /* Set the max number of concurrent connection */ + { "maxqueue", srv_parse_maxqueue, 1, 1, 0 }, /* Set the max number of connection to put in queue */ + { "max-reuse", srv_parse_max_reuse, 1, 1, 0 }, /* Set the max number of requests on a connection, -1 means unlimited */ + { "minconn", srv_parse_minconn, 1, 1, 0 }, /* Enable a dynamic maxconn limit */ + { "namespace", srv_parse_namespace, 1, 1, 0 }, /* Namespace the server socket belongs to (if supported) */ + { "no-backup", srv_parse_no_backup, 0, 1, 0 }, /* Flag as non-backup server */ + { "no-send-proxy", srv_parse_no_send_proxy, 0, 1, 0 }, /* Disable use of PROXY V1 protocol */ + { "no-send-proxy-v2", srv_parse_no_send_proxy_v2, 0, 1, 0 }, /* Disable use of PROXY V2 protocol */ + { "no-tfo", srv_parse_no_tfo, 0, 1, 0 }, /* Disable use of TCP Fast Open */ + { "non-stick", srv_parse_non_stick, 0, 1, 0 }, /* Disable stick-table persistence */ + { "observe", srv_parse_observe, 1, 1, 0 }, /* Enables health adjusting based on observing communication with the server */ + { "on-error", srv_parse_on_error, 1, 1, 0 }, /* Configure the action on check failure */ + { "on-marked-down", srv_parse_on_marked_down, 1, 1, 0 }, /* Configure the action when a server is marked down */ + { "on-marked-up", srv_parse_on_marked_up, 1, 1, 0 }, /* Configure the action when a server is marked up */ + { "pool-low-conn", srv_parse_pool_low_conn, 1, 1, 0 }, /* 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, 0 }, /* Set the max number of orphan idle connections, -1 means unlimited */ + { "pool-purge-delay", srv_parse_pool_purge_delay, 1, 1, 0 }, /* Set the time before we destroy orphan idle connections, defaults to 1s */ + { "proto", srv_parse_proto, 1, 1, 0 }, /* Set the proto to use for all outgoing connections */ + { "proxy-v2-options", srv_parse_proxy_v2_options, 1, 1, 0 }, /* options for send-proxy-v2 */ + { "redir", srv_parse_redir, 1, 1, 0 }, /* Enable redirection mode */ + { "resolve-net", srv_parse_resolve_net, 1, 1, 0 }, /* Set the prefered network range for name resolution */ + { "resolve-opts", srv_parse_resolve_opts, 1, 1, 0 }, /* Set options for name resolution */ + { "resolve-prefer", srv_parse_resolve_prefer, 1, 1, 0 }, /* Set the prefered family for name resolution */ + { "resolvers", srv_parse_resolvers, 1, 1, 0 }, /* Configure the resolver to use for name resolution */ + { "send-proxy", srv_parse_send_proxy, 0, 1, 0 }, /* Enforce use of PROXY V1 protocol */ + { "send-proxy-v2", srv_parse_send_proxy_v2, 0, 1, 0 }, /* Enforce use of PROXY V2 protocol */ + { "slowstart", srv_parse_slowstart, 1, 1, 0 }, /* Set the warm-up timer for a previously failed server */ + { "source", srv_parse_source, -1, 1, 0 }, /* Set the source address to be used to connect to the server */ + { "stick", srv_parse_stick, 0, 1, 0 }, /* Enable stick-table persistence */ + { "tfo", srv_parse_tfo, 0, 1, 0 }, /* enable TCP Fast Open of server */ + { "track", srv_parse_track, 1, 1, 0 }, /* Set the current state of the server, tracking another one */ + { "socks4", srv_parse_socks4, 1, 1, 0 }, /* Set the socks4 proxy of the server*/ + { "usesrc", srv_parse_usesrc, 0, 1, 0 }, /* safe-guard against usesrc without preceding keyword */ + { "weight", srv_parse_weight, 1, 1, 0 }, /* Set the load-balancing weight */ { NULL, NULL, 0 }, }}; @@ -2212,8 +2212,12 @@ void free_server(struct server *srv) srv = NULL; } -/* This function is first intented to be used through parse_server to - * initialize a new server on startup. +/* + * Parse as much as possible such a range string argument: low[-high] + * Set and values so that they may be reused by this loop + * for(int i = nb_low; i <= nb_high; i++)... with nb_low >= 1. + * Fails if 'low' < 0 or 'high' is present and not higher than 'low'. + * Returns 0 if succeeded, -1 if not. */ static int _srv_parse_tmpl_range(struct server *srv, const char *arg, int *nb_low, int *nb_high) @@ -2399,6 +2403,9 @@ static int _srv_parse_init(struct server **srv, char **args, int *cur_arg, newsrv->tmpl_info.nb_high = tmpl_range_high; } + if (parse_flags & SRV_PARSE_DYNAMIC) + newsrv->flags |= SRV_F_DYNAMIC; + /* Note: for a server template, its id is its prefix. * This is a temporary id which will be used for server allocations to come * after parsing. @@ -2466,8 +2473,18 @@ static int _srv_parse_init(struct server **srv, char **args, int *cur_arg, (*cur_arg)++; skip_addr: - /* Copy default server settings to new server settings. */ - srv_settings_cpy(newsrv, &curproxy->defsrv, 0); + if (!(parse_flags & SRV_PARSE_DYNAMIC)) { + /* Copy default server settings to new server */ + srv_settings_cpy(newsrv, &curproxy->defsrv, 0); + } else { + /* Initialize dynamic server weight to 1 */ + newsrv->uweight = newsrv->iweight = 1; + + /* A dynamic server is disabled on startup */ + newsrv->next_admin = SRV_ADMF_FMAINT; + newsrv->next_state = SRV_ST_STOPPED; + server_recalc_eweight(newsrv, 0); + } HA_SPIN_INIT(&newsrv->lock); } else { @@ -2529,6 +2546,12 @@ static int _srv_parse_kw(struct server *srv, char **args, int *cur_arg, err_code = ERR_ALERT; goto out; } + else if ((parse_flags & SRV_PARSE_DYNAMIC) && !kw->dynamic_ok) { + memprintf(errmsg, "'%s' option is not accepted for dynamic server", + args[*cur_arg]); + err_code |= ERR_ALERT; + goto out; + } err_code = kw->parse(args, cur_arg, curproxy, srv, errmsg); @@ -2569,7 +2592,7 @@ static int _srv_parse_sni_expr_init(char **args, int cur_arg, */ static int _srv_parse_finalize(char **args, int cur_arg, struct server *srv, struct proxy *px, - char **errmsg) + int parse_flags, char **errmsg) { #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME int ret; @@ -2591,10 +2614,16 @@ static int _srv_parse_finalize(char **args, int cur_arg, return ret; #endif - if (srv->flags & SRV_F_BACKUP) - px->srv_bck++; - else - px->srv_act++; + /* A dynamic server is disabled on startup. It must not be counted as + * an active backend entry. + */ + if (!(parse_flags & SRV_PARSE_DYNAMIC)) { + if (srv->flags & SRV_F_BACKUP) + px->srv_bck++; + else + px->srv_act++; + } + srv_lb_commit_status(srv); return 0; @@ -2660,7 +2689,7 @@ int parse_server(const char *file, int linenum, char **args, } if (!(parse_flags & SRV_PARSE_DEFAULT_SERVER)) { - err_code |= _srv_parse_finalize(args, cur_arg, newsrv, curproxy, &errmsg); + err_code |= _srv_parse_finalize(args, cur_arg, newsrv, curproxy, parse_flags, &errmsg); if (err_code) { display_parser_err(file, linenum, args, cur_arg, err_code, &errmsg); free(errmsg);